diff --git a/cmd/istanbul/cmd.go b/cmd/istanbul/cmd.go index d423f6a6..f784a17e 100644 --- a/cmd/istanbul/cmd.go +++ b/cmd/istanbul/cmd.go @@ -17,14 +17,11 @@ package main import ( - "bytes" "fmt" "os" "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/rlp" + "github.com/getamis/istanbul-tools/cmd/istanbul/extradata" "github.com/naoina/toml" "github.com/urfave/cli" ) @@ -67,33 +64,37 @@ func encode(ctx *cli.Context) error { } if len(path) != 0 { - if err := fromConfig(path); err != nil { + extraData, err := fromConfig(path) + if err != nil { return cli.NewExitError("Failed to encode from config data", 0) } + fmt.Println("Encoded Istanbul extra-data:", extraData) } if len(validators) != 0 { - if err := fromRawData(ctx.String(VanityFlag.Name), validators); err != nil { + extraData, err := fromRawData(ctx.String(VanityFlag.Name), validators) + if err != nil { return cli.NewExitError("Failed to encode from flags", 0) } + fmt.Println("Encoded Istanbul extra-data:", extraData) } return nil } -func fromRawData(vanity string, validators string) error { +func fromRawData(vanity string, validators string) (string, error) { vs := splitAndTrim(validators) addrs := make([]common.Address, len(vs)) for i, v := range vs { addrs[i] = common.HexToAddress(v) } - return encodeExtraData(vanity, addrs) + return extradata.Encode(vanity, addrs) } -func fromConfig(path string) error { +func fromConfig(path string) (string, error) { file, err := os.Open(path) if err != nil { - return cli.NewExitError(fmt.Sprintf("Failed to read config file: %v", err), 1) + return "", cli.NewExitError(fmt.Sprintf("Failed to read config file: %v", err), 1) } defer file.Close() @@ -103,10 +104,10 @@ func fromConfig(path string) error { } if err := toml.NewDecoder(file).Decode(&config); err != nil { - return cli.NewExitError(fmt.Sprintf("Failed to parse config file: %v", err), 2) + return "", cli.NewExitError(fmt.Sprintf("Failed to parse config file: %v", err), 2) } - return encodeExtraData(config.Vanity, config.Validators) + return extradata.Encode(config.Vanity, config.Validators) } func decode(ctx *cli.Context) error { @@ -114,47 +115,13 @@ func decode(ctx *cli.Context) error { return cli.NewExitError("Must supply extra data", 10) } - return decodeExtraData(ctx.String(ExtraDataFlag.Name)) -} - -func encodeExtraData(vanity string, validators []common.Address) error { - newVanity, err := hexutil.Decode(vanity) + extraString := ctx.String(ExtraDataFlag.Name) + vanity, istanbulExtra, err := extradata.Decode(extraString) if err != nil { return err } - if len(newVanity) < types.IstanbulExtraVanity { - newVanity = append(newVanity, bytes.Repeat([]byte{0x00}, types.IstanbulExtraVanity-len(newVanity))...) - } - newVanity = newVanity[:types.IstanbulExtraVanity] - - ist := &types.IstanbulExtra{ - Validators: validators, - Seal: make([]byte, types.IstanbulExtraSeal), - CommittedSeal: [][]byte{}, - } - - payload, err := rlp.EncodeToBytes(&ist) - if err != nil { - return err - } - fmt.Println("Encoded Istanbul extra-data:", "0x"+common.Bytes2Hex(append(newVanity, payload...))) - - return nil -} - -func decodeExtraData(extraData string) error { - extra, err := hexutil.Decode(extraData) - if err != nil { - return err - } - - istanbulExtra, err := types.ExtractIstanbulExtra(&types.Header{Extra: extra}) - if err != nil { - return err - } - - fmt.Println("vanity: ", "0x"+common.Bytes2Hex(extra[:types.IstanbulExtraVanity])) + fmt.Println("vanity: ", "0x"+common.Bytes2Hex(vanity)) for _, v := range istanbulExtra.Validators { fmt.Println("validator: ", v.Hex()) diff --git a/cmd/istanbul/extradata/decoder.go b/cmd/istanbul/extradata/decoder.go new file mode 100644 index 00000000..031a1a45 --- /dev/null +++ b/cmd/istanbul/extradata/decoder.go @@ -0,0 +1,19 @@ +package extradata + +import ( + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/core/types" +) + +func Decode(extraData string) ([]byte, *types.IstanbulExtra, error) { + extra, err := hexutil.Decode(extraData) + if err != nil { + return nil, nil, err + } + + istanbulExtra, err := types.ExtractIstanbulExtra(&types.Header{Extra: extra}) + if err != nil { + return nil, nil, err + } + return extra[:types.IstanbulExtraVanity], istanbulExtra, nil +} diff --git a/cmd/istanbul/extradata/encoder.go b/cmd/istanbul/extradata/encoder.go new file mode 100644 index 00000000..ad7efb3f --- /dev/null +++ b/cmd/istanbul/extradata/encoder.go @@ -0,0 +1,35 @@ +package extradata + +import ( + "bytes" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/rlp" + atypes "github.com/getamis/go-ethereum/core/types" +) + +func Encode(vanity string, validators []common.Address) (string, error) { + newVanity, err := hexutil.Decode(vanity) + if err != nil { + return "", err + } + + if len(newVanity) < atypes.IstanbulExtraVanity { + newVanity = append(newVanity, bytes.Repeat([]byte{0x00}, atypes.IstanbulExtraVanity-len(newVanity))...) + } + newVanity = newVanity[:atypes.IstanbulExtraVanity] + + ist := &atypes.IstanbulExtra{ + Validators: validators, + Seal: make([]byte, atypes.IstanbulExtraSeal), + CommittedSeal: [][]byte{}, + } + + payload, err := rlp.EncodeToBytes(&ist) + if err != nil { + return "", err + } + + return "0x" + common.Bytes2Hex(append(newVanity, payload...)), nil +} diff --git a/core/cluster.go b/core/cluster.go new file mode 100644 index 00000000..6f6e3663 --- /dev/null +++ b/core/cluster.go @@ -0,0 +1,166 @@ +// Copyright 2017 AMIS Technologies +// 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 ( + "crypto/ecdsa" + "encoding/json" + "fmt" + "io/ioutil" + "log" + "net" + "os" + "path/filepath" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/p2p/discover" + "github.com/satori/go.uuid" +) + +const ( + defaultBaseRpcPort = uint16(8545) + defaultHttpPort = uint16(30303) + + defaultLocalDir = "/tmp/gdata" + datadirPrivateKey = "nodekey" + defaultIP = "localhost" + + clientIdentifier = "geth" + staticNodeJson = "static-nodes.json" + genesisJson = "genesis.json" +) + +func GenerateClusterKeys(numbers int) []*ecdsa.PrivateKey { + keys := make([]*ecdsa.PrivateKey, numbers) + for i := 0; i < len(keys); i++ { + key, err := crypto.GenerateKey() + if err != nil { + panic("couldn't generate key: " + err.Error()) + } + keys[i] = key + } + return keys +} + +type Env struct { + GethID int + HttpPort uint16 + RpcPort uint16 + DataDir string + Key *ecdsa.PrivateKey +} + +func SetupEnv(prvKeys []*ecdsa.PrivateKey) []*Env { + envs := make([]*Env, len(prvKeys)) + rpcPort := defaultBaseRpcPort + httpPort := defaultHttpPort + + for i := 0; i < len(envs); i++ { + dataDir, err := saveNodeKey(prvKeys[i]) + if err != nil { + panic("Failed to save node key") + } + + envs[i] = &Env{ + GethID: i, + HttpPort: httpPort, + RpcPort: rpcPort, + DataDir: dataDir, + Key: prvKeys[i], + } + + rpcPort = rpcPort + 1 + httpPort = httpPort + 1 + } + return envs +} + +func SetupNodes(envs []*Env) error { + nodes := transformToStaticNodes(envs) + for _, env := range envs { + if err := saveStaticNode(env.DataDir, nodes); err != nil { + return err + } + } + + addrs := transformToAddress(envs) + genesis := GenerateGenesis(addrs) + for _, env := range envs { + if err := saveGenesis(env.DataDir, genesis); err != nil { + return err + } + } + return nil +} + +func saveNodeKey(key *ecdsa.PrivateKey) (string, error) { + err := os.MkdirAll(filepath.Join(defaultLocalDir), 0700) + if err != nil { + log.Fatal(err) + } + + instanceDir := filepath.Join(defaultLocalDir, fmt.Sprintf("%s%s", clientIdentifier, uuid.NewV4().String())) + if err := os.MkdirAll(instanceDir, 0700); err != nil { + log.Println(fmt.Sprintf("Failed to create instance dir: %v", err)) + return "", err + } + + keyDir := filepath.Join(instanceDir, clientIdentifier) + if err := os.MkdirAll(keyDir, 0700); err != nil { + log.Println(fmt.Sprintf("Failed to create key dir: %v", err)) + return "", err + } + + keyfile := filepath.Join(keyDir, datadirPrivateKey) + if err := crypto.SaveECDSA(keyfile, key); err != nil { + log.Println(fmt.Sprintf("Failed to persist node key: %v", err)) + return "", err + } + return instanceDir, nil +} + +func saveStaticNode(dataDir string, nodes []*discover.Node) error { + filePath := filepath.Join(dataDir, clientIdentifier) + keyPath := filepath.Join(filePath, staticNodeJson) + + raw, err := json.Marshal(nodes) + if err != nil { + return err + } + + return ioutil.WriteFile(keyPath, raw, 0600) +} + +func transformToStaticNodes(envs []*Env) []*discover.Node { + nodes := make([]*discover.Node, len(envs)) + + for i, env := range envs { + nodeID := discover.PubkeyID(&env.Key.PublicKey) + nodes[i] = discover.NewNode(nodeID, net.ParseIP(defaultIP), 0, env.HttpPort) + } + return nodes +} + +func transformToAddress(envs []*Env) []common.Address { + addrs := make([]common.Address, len(envs)) + + for i, env := range envs { + addrs[i] = crypto.PubkeyToAddress(env.Key.PublicKey) + } + return addrs +} diff --git a/core/cluster_test.go b/core/cluster_test.go new file mode 100644 index 00000000..f5088101 --- /dev/null +++ b/core/cluster_test.go @@ -0,0 +1,34 @@ +// Copyright 2017 AMIS Technologies +// 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 ( + "fmt" + "testing" +) + +func TestWriteFile(t *testing.T) { + keys := GenerateClusterKeys(4) + envs := SetupEnv(keys) + err := SetupNodes(envs) + if err != nil { + t.Fatal("failed to setup nodes", err) + } + for _, env := range envs { + fmt.Println(fmt.Sprintf("%s%d%s%s", "geth ID:", env.GethID, ", dataDir:", env.DataDir)) + } +} diff --git a/core/genesis.go b/core/genesis.go new file mode 100644 index 00000000..4a9cdf9e --- /dev/null +++ b/core/genesis.go @@ -0,0 +1,71 @@ +// Copyright 2017 AMIS Technologies +// 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" + "io/ioutil" + "math/big" + "path/filepath" + "time" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/consensus/istanbul" + "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/params" + "github.com/getamis/istanbul-tools/cmd/istanbul/extradata" +) + +func GenerateGenesis(addrs []common.Address) *core.Genesis { + extraData, err := extradata.Encode("0x00", addrs) + if err != nil { + panic(fmt.Sprintf("%s%s", "Failed to generate genesis", err)) + } + + return &core.Genesis{ + Timestamp: uint64(time.Now().Unix()), + GasLimit: 4700000, + Difficulty: big.NewInt(1), + Alloc: make(core.GenesisAlloc), + Config: ¶ms.ChainConfig{ + HomesteadBlock: big.NewInt(1), + EIP150Block: big.NewInt(2), + EIP155Block: big.NewInt(3), + EIP158Block: big.NewInt(3), + Istanbul: ¶ms.IstanbulConfig{ + ProposerPolicy: uint64(istanbul.DefaultConfig.ProposerPolicy), + Epoch: istanbul.DefaultConfig.Epoch, + }, + }, + Mixhash: types.IstanbulDigest, + ExtraData: hexutil.MustDecode(extraData), + } +} + +func saveGenesis(dataDir string, genesis *core.Genesis) error { + filePath := filepath.Join(dataDir, genesisJson) + + raw, err := json.Marshal(genesis) + if err != nil { + return err + } + + return ioutil.WriteFile(filePath, raw, 0600) +} diff --git a/glide.lock b/glide.lock index 7370d1c8..57a1e9c6 100644 --- a/glide.lock +++ b/glide.lock @@ -1,5 +1,5 @@ -hash: eb90dd3f38fb4dead998c624f39c7897e252105342c15e909f32835eb99d65fc -updated: 2017-08-09T16:37:30.171348623+08:00 +hash: 89546c4f43145476a4e79907fdddddd9e982ddb8e035db13051ef08d03f07dcf +updated: 2017-08-11T13:30:18.848541104+08:00 imports: - name: github.com/aristanetworks/goarista version: 8e44bec0a94d7c1f0cdf28ed5215e5cfab441ad0 @@ -115,6 +115,7 @@ imports: version: 0f066fb0e5977635e543b2c8d008405c5abb734b subpackages: - cmd/utils + - core/types - name: github.com/go-stack/stack version: 817915b46b97fd7bb80e8ab6b69f01a53ac3eebf - name: github.com/gogo/protobuf @@ -180,6 +181,8 @@ imports: - token - name: github.com/rs/cors version: eabcc6af4bbe5ad3a949d36450326a2b0b9894b8 +- name: github.com/satori/go.uuid + version: 879c5887cd475cd7864858769793b2ceb0d44feb - name: github.com/sirupsen/logrus version: 181d419aa9e2223811b824e8f0b4af96f9ba9302 - name: github.com/syndtr/goleveldb diff --git a/glide.yaml b/glide.yaml index c750a481..58f23a93 100644 --- a/glide.yaml +++ b/glide.yaml @@ -2,8 +2,8 @@ package: github.com/getamis/istanbul-tools import: - package: github.com/ethereum/go-ethereum version: istanbul/develop - repo: git@github.com:getamis/go-ethereum - vcs: git + repo: git@github.com:getamis/go-ethereum + vcs: git subpackages: - cmd/utils - common @@ -20,3 +20,5 @@ import: - package: github.com/naoina/toml - package: github.com/urfave/cli - package: github.com/opencontainers/go-digest +- package: github.com/satori/go.uuid + version: ~1.1.0 diff --git a/vendor/github.com/satori/go.uuid/.travis.yml b/vendor/github.com/satori/go.uuid/.travis.yml new file mode 100644 index 00000000..38517e2e --- /dev/null +++ b/vendor/github.com/satori/go.uuid/.travis.yml @@ -0,0 +1,15 @@ +language: go +sudo: false +go: + - 1.2 + - 1.3 + - 1.4 + - 1.5 + - 1.6 +before_install: + - go get github.com/mattn/goveralls + - go get golang.org/x/tools/cmd/cover +script: + - $HOME/gopath/bin/goveralls -service=travis-ci +notifications: + email: false diff --git a/vendor/github.com/satori/go.uuid/LICENSE b/vendor/github.com/satori/go.uuid/LICENSE new file mode 100644 index 00000000..488357b8 --- /dev/null +++ b/vendor/github.com/satori/go.uuid/LICENSE @@ -0,0 +1,20 @@ +Copyright (C) 2013-2016 by Maxim Bublis + +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/satori/go.uuid/README.md b/vendor/github.com/satori/go.uuid/README.md new file mode 100644 index 00000000..b6aad1c8 --- /dev/null +++ b/vendor/github.com/satori/go.uuid/README.md @@ -0,0 +1,65 @@ +# UUID package for Go language + +[![Build Status](https://travis-ci.org/satori/go.uuid.png?branch=master)](https://travis-ci.org/satori/go.uuid) +[![Coverage Status](https://coveralls.io/repos/github/satori/go.uuid/badge.svg?branch=master)](https://coveralls.io/github/satori/go.uuid) +[![GoDoc](http://godoc.org/github.com/satori/go.uuid?status.png)](http://godoc.org/github.com/satori/go.uuid) + +This package provides pure Go implementation of Universally Unique Identifier (UUID). Supported both creation and parsing of UUIDs. + +With 100% test coverage and benchmarks out of box. + +Supported versions: +* Version 1, based on timestamp and MAC address (RFC 4122) +* Version 2, based on timestamp, MAC address and POSIX UID/GID (DCE 1.1) +* Version 3, based on MD5 hashing (RFC 4122) +* Version 4, based on random numbers (RFC 4122) +* Version 5, based on SHA-1 hashing (RFC 4122) + +## Installation + +Use the `go` command: + + $ go get github.com/satori/go.uuid + +## Requirements + +UUID package requires Go >= 1.2. + +## Example + +```go +package main + +import ( + "fmt" + "github.com/satori/go.uuid" +) + +func main() { + // Creating UUID Version 4 + u1 := uuid.NewV4() + fmt.Printf("UUIDv4: %s\n", u1) + + // Parsing UUID from string input + u2, err := uuid.FromString("6ba7b810-9dad-11d1-80b4-00c04fd430c8") + if err != nil { + fmt.Printf("Something gone wrong: %s", err) + } + fmt.Printf("Successfully parsed: %s", u2) +} +``` + +## Documentation + +[Documentation](http://godoc.org/github.com/satori/go.uuid) is hosted at GoDoc project. + +## Links +* [RFC 4122](http://tools.ietf.org/html/rfc4122) +* [DCE 1.1: Authentication and Security Services](http://pubs.opengroup.org/onlinepubs/9696989899/chap5.htm#tagcjh_08_02_01_01) + +## Copyright + +Copyright (C) 2013-2016 by Maxim Bublis . + +UUID package released under MIT License. +See [LICENSE](https://github.com/satori/go.uuid/blob/master/LICENSE) for details. diff --git a/vendor/github.com/satori/go.uuid/benchmarks_test.go b/vendor/github.com/satori/go.uuid/benchmarks_test.go new file mode 100644 index 00000000..b4e567fc --- /dev/null +++ b/vendor/github.com/satori/go.uuid/benchmarks_test.go @@ -0,0 +1,121 @@ +// Copyright (C) 2013-2015 by Maxim Bublis +// +// 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. + +package uuid + +import ( + "testing" +) + +func BenchmarkFromBytes(b *testing.B) { + bytes := []byte{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} + for i := 0; i < b.N; i++ { + FromBytes(bytes) + } +} + +func BenchmarkFromString(b *testing.B) { + s := "6ba7b810-9dad-11d1-80b4-00c04fd430c8" + for i := 0; i < b.N; i++ { + FromString(s) + } +} + +func BenchmarkFromStringUrn(b *testing.B) { + s := "urn:uuid:6ba7b810-9dad-11d1-80b4-00c04fd430c8" + for i := 0; i < b.N; i++ { + FromString(s) + } +} + +func BenchmarkFromStringWithBrackets(b *testing.B) { + s := "{6ba7b810-9dad-11d1-80b4-00c04fd430c8}" + for i := 0; i < b.N; i++ { + FromString(s) + } +} + +func BenchmarkNewV1(b *testing.B) { + for i := 0; i < b.N; i++ { + NewV1() + } +} + +func BenchmarkNewV2(b *testing.B) { + for i := 0; i < b.N; i++ { + NewV2(DomainPerson) + } +} + +func BenchmarkNewV3(b *testing.B) { + for i := 0; i < b.N; i++ { + NewV3(NamespaceDNS, "www.example.com") + } +} + +func BenchmarkNewV4(b *testing.B) { + for i := 0; i < b.N; i++ { + NewV4() + } +} + +func BenchmarkNewV5(b *testing.B) { + for i := 0; i < b.N; i++ { + NewV5(NamespaceDNS, "www.example.com") + } +} + +func BenchmarkMarshalBinary(b *testing.B) { + u := NewV4() + for i := 0; i < b.N; i++ { + u.MarshalBinary() + } +} + +func BenchmarkMarshalText(b *testing.B) { + u := NewV4() + for i := 0; i < b.N; i++ { + u.MarshalText() + } +} + +func BenchmarkUnmarshalBinary(b *testing.B) { + bytes := []byte{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} + u := UUID{} + for i := 0; i < b.N; i++ { + u.UnmarshalBinary(bytes) + } +} + +func BenchmarkUnmarshalText(b *testing.B) { + bytes := []byte("6ba7b810-9dad-11d1-80b4-00c04fd430c8") + u := UUID{} + for i := 0; i < b.N; i++ { + u.UnmarshalText(bytes) + } +} + +func BenchmarkMarshalToString(b *testing.B) { + u := NewV4() + for i := 0; i < b.N; i++ { + u.String() + } +} diff --git a/vendor/github.com/satori/go.uuid/uuid.go b/vendor/github.com/satori/go.uuid/uuid.go new file mode 100644 index 00000000..9c7fbaa5 --- /dev/null +++ b/vendor/github.com/satori/go.uuid/uuid.go @@ -0,0 +1,488 @@ +// Copyright (C) 2013-2015 by Maxim Bublis +// +// 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. + +// Package uuid provides implementation of Universally Unique Identifier (UUID). +// Supported versions are 1, 3, 4 and 5 (as specified in RFC 4122) and +// version 2 (as specified in DCE 1.1). +package uuid + +import ( + "bytes" + "crypto/md5" + "crypto/rand" + "crypto/sha1" + "database/sql/driver" + "encoding/binary" + "encoding/hex" + "fmt" + "hash" + "net" + "os" + "sync" + "time" +) + +// UUID layout variants. +const ( + VariantNCS = iota + VariantRFC4122 + VariantMicrosoft + VariantFuture +) + +// UUID DCE domains. +const ( + DomainPerson = iota + DomainGroup + DomainOrg +) + +// Difference in 100-nanosecond intervals between +// UUID epoch (October 15, 1582) and Unix epoch (January 1, 1970). +const epochStart = 122192928000000000 + +// Used in string method conversion +const dash byte = '-' + +// UUID v1/v2 storage. +var ( + storageMutex sync.Mutex + storageOnce sync.Once + epochFunc = unixTimeFunc + clockSequence uint16 + lastTime uint64 + hardwareAddr [6]byte + posixUID = uint32(os.Getuid()) + posixGID = uint32(os.Getgid()) +) + +// String parse helpers. +var ( + urnPrefix = []byte("urn:uuid:") + byteGroups = []int{8, 4, 4, 4, 12} +) + +func initClockSequence() { + buf := make([]byte, 2) + safeRandom(buf) + clockSequence = binary.BigEndian.Uint16(buf) +} + +func initHardwareAddr() { + interfaces, err := net.Interfaces() + if err == nil { + for _, iface := range interfaces { + if len(iface.HardwareAddr) >= 6 { + copy(hardwareAddr[:], iface.HardwareAddr) + return + } + } + } + + // Initialize hardwareAddr randomly in case + // of real network interfaces absence + safeRandom(hardwareAddr[:]) + + // Set multicast bit as recommended in RFC 4122 + hardwareAddr[0] |= 0x01 +} + +func initStorage() { + initClockSequence() + initHardwareAddr() +} + +func safeRandom(dest []byte) { + if _, err := rand.Read(dest); err != nil { + panic(err) + } +} + +// Returns difference in 100-nanosecond intervals between +// UUID epoch (October 15, 1582) and current time. +// This is default epoch calculation function. +func unixTimeFunc() uint64 { + return epochStart + uint64(time.Now().UnixNano()/100) +} + +// UUID representation compliant with specification +// described in RFC 4122. +type UUID [16]byte + +// NullUUID can be used with the standard sql package to represent a +// UUID value that can be NULL in the database +type NullUUID struct { + UUID UUID + Valid bool +} + +// The nil UUID is special form of UUID that is specified to have all +// 128 bits set to zero. +var Nil = UUID{} + +// Predefined namespace UUIDs. +var ( + NamespaceDNS, _ = FromString("6ba7b810-9dad-11d1-80b4-00c04fd430c8") + NamespaceURL, _ = FromString("6ba7b811-9dad-11d1-80b4-00c04fd430c8") + NamespaceOID, _ = FromString("6ba7b812-9dad-11d1-80b4-00c04fd430c8") + NamespaceX500, _ = FromString("6ba7b814-9dad-11d1-80b4-00c04fd430c8") +) + +// And returns result of binary AND of two UUIDs. +func And(u1 UUID, u2 UUID) UUID { + u := UUID{} + for i := 0; i < 16; i++ { + u[i] = u1[i] & u2[i] + } + return u +} + +// Or returns result of binary OR of two UUIDs. +func Or(u1 UUID, u2 UUID) UUID { + u := UUID{} + for i := 0; i < 16; i++ { + u[i] = u1[i] | u2[i] + } + return u +} + +// Equal returns true if u1 and u2 equals, otherwise returns false. +func Equal(u1 UUID, u2 UUID) bool { + return bytes.Equal(u1[:], u2[:]) +} + +// Version returns algorithm version used to generate UUID. +func (u UUID) Version() uint { + return uint(u[6] >> 4) +} + +// Variant returns UUID layout variant. +func (u UUID) Variant() uint { + switch { + case (u[8] & 0x80) == 0x00: + return VariantNCS + case (u[8]&0xc0)|0x80 == 0x80: + return VariantRFC4122 + case (u[8]&0xe0)|0xc0 == 0xc0: + return VariantMicrosoft + } + return VariantFuture +} + +// Bytes returns bytes slice representation of UUID. +func (u UUID) Bytes() []byte { + return u[:] +} + +// Returns canonical string representation of UUID: +// xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx. +func (u UUID) String() string { + buf := make([]byte, 36) + + hex.Encode(buf[0:8], u[0:4]) + buf[8] = dash + hex.Encode(buf[9:13], u[4:6]) + buf[13] = dash + hex.Encode(buf[14:18], u[6:8]) + buf[18] = dash + hex.Encode(buf[19:23], u[8:10]) + buf[23] = dash + hex.Encode(buf[24:], u[10:]) + + return string(buf) +} + +// SetVersion sets version bits. +func (u *UUID) SetVersion(v byte) { + u[6] = (u[6] & 0x0f) | (v << 4) +} + +// SetVariant sets variant bits as described in RFC 4122. +func (u *UUID) SetVariant() { + u[8] = (u[8] & 0xbf) | 0x80 +} + +// MarshalText implements the encoding.TextMarshaler interface. +// The encoding is the same as returned by String. +func (u UUID) MarshalText() (text []byte, err error) { + text = []byte(u.String()) + return +} + +// UnmarshalText implements the encoding.TextUnmarshaler interface. +// Following formats are supported: +// "6ba7b810-9dad-11d1-80b4-00c04fd430c8", +// "{6ba7b810-9dad-11d1-80b4-00c04fd430c8}", +// "urn:uuid:6ba7b810-9dad-11d1-80b4-00c04fd430c8" +func (u *UUID) UnmarshalText(text []byte) (err error) { + if len(text) < 32 { + err = fmt.Errorf("uuid: UUID string too short: %s", text) + return + } + + t := text[:] + braced := false + + if bytes.Equal(t[:9], urnPrefix) { + t = t[9:] + } else if t[0] == '{' { + braced = true + t = t[1:] + } + + b := u[:] + + for i, byteGroup := range byteGroups { + if i > 0 && t[0] == '-' { + t = t[1:] + } else if i > 0 && t[0] != '-' { + err = fmt.Errorf("uuid: invalid string format") + return + } + + if i == 2 { + if !bytes.Contains([]byte("012345"), []byte{t[0]}) { + err = fmt.Errorf("uuid: invalid version number: %s", t[0]) + return + } + } + + if len(t) < byteGroup { + err = fmt.Errorf("uuid: UUID string too short: %s", text) + return + } + + if i == 4 && len(t) > byteGroup && + ((braced && t[byteGroup] != '}') || len(t[byteGroup:]) > 1 || !braced) { + err = fmt.Errorf("uuid: UUID string too long: %s", t) + return + } + + _, err = hex.Decode(b[:byteGroup/2], t[:byteGroup]) + + if err != nil { + return + } + + t = t[byteGroup:] + b = b[byteGroup/2:] + } + + return +} + +// MarshalBinary implements the encoding.BinaryMarshaler interface. +func (u UUID) MarshalBinary() (data []byte, err error) { + data = u.Bytes() + return +} + +// UnmarshalBinary implements the encoding.BinaryUnmarshaler interface. +// It will return error if the slice isn't 16 bytes long. +func (u *UUID) UnmarshalBinary(data []byte) (err error) { + if len(data) != 16 { + err = fmt.Errorf("uuid: UUID must be exactly 16 bytes long, got %d bytes", len(data)) + return + } + copy(u[:], data) + + return +} + +// Value implements the driver.Valuer interface. +func (u UUID) Value() (driver.Value, error) { + return u.String(), nil +} + +// Scan implements the sql.Scanner interface. +// A 16-byte slice is handled by UnmarshalBinary, while +// a longer byte slice or a string is handled by UnmarshalText. +func (u *UUID) Scan(src interface{}) error { + switch src := src.(type) { + case []byte: + if len(src) == 16 { + return u.UnmarshalBinary(src) + } + return u.UnmarshalText(src) + + case string: + return u.UnmarshalText([]byte(src)) + } + + return fmt.Errorf("uuid: cannot convert %T to UUID", src) +} + +// Value implements the driver.Valuer interface. +func (u NullUUID) Value() (driver.Value, error) { + if !u.Valid { + return nil, nil + } + // Delegate to UUID Value function + return u.UUID.Value() +} + +// Scan implements the sql.Scanner interface. +func (u *NullUUID) Scan(src interface{}) error { + if src == nil { + u.UUID, u.Valid = Nil, false + return nil + } + + // Delegate to UUID Scan function + u.Valid = true + return u.UUID.Scan(src) +} + +// FromBytes returns UUID converted from raw byte slice input. +// It will return error if the slice isn't 16 bytes long. +func FromBytes(input []byte) (u UUID, err error) { + err = u.UnmarshalBinary(input) + return +} + +// FromBytesOrNil returns UUID converted from raw byte slice input. +// Same behavior as FromBytes, but returns a Nil UUID on error. +func FromBytesOrNil(input []byte) UUID { + uuid, err := FromBytes(input) + if err != nil { + return Nil + } + return uuid +} + +// FromString returns UUID parsed from string input. +// Input is expected in a form accepted by UnmarshalText. +func FromString(input string) (u UUID, err error) { + err = u.UnmarshalText([]byte(input)) + return +} + +// FromStringOrNil returns UUID parsed from string input. +// Same behavior as FromString, but returns a Nil UUID on error. +func FromStringOrNil(input string) UUID { + uuid, err := FromString(input) + if err != nil { + return Nil + } + return uuid +} + +// Returns UUID v1/v2 storage state. +// Returns epoch timestamp, clock sequence, and hardware address. +func getStorage() (uint64, uint16, []byte) { + storageOnce.Do(initStorage) + + storageMutex.Lock() + defer storageMutex.Unlock() + + timeNow := epochFunc() + // Clock changed backwards since last UUID generation. + // Should increase clock sequence. + if timeNow <= lastTime { + clockSequence++ + } + lastTime = timeNow + + return timeNow, clockSequence, hardwareAddr[:] +} + +// NewV1 returns UUID based on current timestamp and MAC address. +func NewV1() UUID { + u := UUID{} + + timeNow, clockSeq, hardwareAddr := getStorage() + + binary.BigEndian.PutUint32(u[0:], uint32(timeNow)) + binary.BigEndian.PutUint16(u[4:], uint16(timeNow>>32)) + binary.BigEndian.PutUint16(u[6:], uint16(timeNow>>48)) + binary.BigEndian.PutUint16(u[8:], clockSeq) + + copy(u[10:], hardwareAddr) + + u.SetVersion(1) + u.SetVariant() + + return u +} + +// NewV2 returns DCE Security UUID based on POSIX UID/GID. +func NewV2(domain byte) UUID { + u := UUID{} + + timeNow, clockSeq, hardwareAddr := getStorage() + + switch domain { + case DomainPerson: + binary.BigEndian.PutUint32(u[0:], posixUID) + case DomainGroup: + binary.BigEndian.PutUint32(u[0:], posixGID) + } + + binary.BigEndian.PutUint16(u[4:], uint16(timeNow>>32)) + binary.BigEndian.PutUint16(u[6:], uint16(timeNow>>48)) + binary.BigEndian.PutUint16(u[8:], clockSeq) + u[9] = domain + + copy(u[10:], hardwareAddr) + + u.SetVersion(2) + u.SetVariant() + + return u +} + +// NewV3 returns UUID based on MD5 hash of namespace UUID and name. +func NewV3(ns UUID, name string) UUID { + u := newFromHash(md5.New(), ns, name) + u.SetVersion(3) + u.SetVariant() + + return u +} + +// NewV4 returns random generated UUID. +func NewV4() UUID { + u := UUID{} + safeRandom(u[:]) + u.SetVersion(4) + u.SetVariant() + + return u +} + +// NewV5 returns UUID based on SHA-1 hash of namespace UUID and name. +func NewV5(ns UUID, name string) UUID { + u := newFromHash(sha1.New(), ns, name) + u.SetVersion(5) + u.SetVariant() + + return u +} + +// Returns UUID based on hashing of namespace UUID and name. +func newFromHash(h hash.Hash, ns UUID, name string) UUID { + u := UUID{} + h.Write(ns[:]) + h.Write([]byte(name)) + copy(u[:], h.Sum(nil)) + + return u +} diff --git a/vendor/github.com/satori/go.uuid/uuid_test.go b/vendor/github.com/satori/go.uuid/uuid_test.go new file mode 100644 index 00000000..aa68ac94 --- /dev/null +++ b/vendor/github.com/satori/go.uuid/uuid_test.go @@ -0,0 +1,633 @@ +// Copyright (C) 2013, 2015 by Maxim Bublis +// +// 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. + +package uuid + +import ( + "bytes" + "testing" +) + +func TestBytes(t *testing.T) { + u := UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} + + bytes1 := []byte{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} + + if !bytes.Equal(u.Bytes(), bytes1) { + t.Errorf("Incorrect bytes representation for UUID: %s", u) + } +} + +func TestString(t *testing.T) { + if NamespaceDNS.String() != "6ba7b810-9dad-11d1-80b4-00c04fd430c8" { + t.Errorf("Incorrect string representation for UUID: %s", NamespaceDNS.String()) + } +} + +func TestEqual(t *testing.T) { + if !Equal(NamespaceDNS, NamespaceDNS) { + t.Errorf("Incorrect comparison of %s and %s", NamespaceDNS, NamespaceDNS) + } + + if Equal(NamespaceDNS, NamespaceURL) { + t.Errorf("Incorrect comparison of %s and %s", NamespaceDNS, NamespaceURL) + } +} + +func TestOr(t *testing.T) { + u1 := UUID{0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff} + u2 := UUID{0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00} + + u := UUID{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff} + + if !Equal(u, Or(u1, u2)) { + t.Errorf("Incorrect bitwise OR result %s", Or(u1, u2)) + } +} + +func TestAnd(t *testing.T) { + u1 := UUID{0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff} + u2 := UUID{0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00} + + u := UUID{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} + + if !Equal(u, And(u1, u2)) { + t.Errorf("Incorrect bitwise AND result %s", And(u1, u2)) + } +} + +func TestVersion(t *testing.T) { + u := UUID{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} + + if u.Version() != 1 { + t.Errorf("Incorrect version for UUID: %d", u.Version()) + } +} + +func TestSetVersion(t *testing.T) { + u := UUID{} + u.SetVersion(4) + + if u.Version() != 4 { + t.Errorf("Incorrect version for UUID after u.setVersion(4): %d", u.Version()) + } +} + +func TestVariant(t *testing.T) { + u1 := UUID{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} + + if u1.Variant() != VariantNCS { + t.Errorf("Incorrect variant for UUID variant %d: %d", VariantNCS, u1.Variant()) + } + + u2 := UUID{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} + + if u2.Variant() != VariantRFC4122 { + t.Errorf("Incorrect variant for UUID variant %d: %d", VariantRFC4122, u2.Variant()) + } + + u3 := UUID{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} + + if u3.Variant() != VariantMicrosoft { + t.Errorf("Incorrect variant for UUID variant %d: %d", VariantMicrosoft, u3.Variant()) + } + + u4 := UUID{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} + + if u4.Variant() != VariantFuture { + t.Errorf("Incorrect variant for UUID variant %d: %d", VariantFuture, u4.Variant()) + } +} + +func TestSetVariant(t *testing.T) { + u := new(UUID) + u.SetVariant() + + if u.Variant() != VariantRFC4122 { + t.Errorf("Incorrect variant for UUID after u.setVariant(): %d", u.Variant()) + } +} + +func TestFromBytes(t *testing.T) { + u := UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} + b1 := []byte{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} + + u1, err := FromBytes(b1) + if err != nil { + t.Errorf("Error parsing UUID from bytes: %s", err) + } + + if !Equal(u, u1) { + t.Errorf("UUIDs should be equal: %s and %s", u, u1) + } + + b2 := []byte{} + + _, err = FromBytes(b2) + if err == nil { + t.Errorf("Should return error parsing from empty byte slice, got %s", err) + } +} + +func TestMarshalBinary(t *testing.T) { + u := UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} + b1 := []byte{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} + + b2, err := u.MarshalBinary() + if err != nil { + t.Errorf("Error marshaling UUID: %s", err) + } + + if !bytes.Equal(b1, b2) { + t.Errorf("Marshaled UUID should be %s, got %s", b1, b2) + } +} + +func TestUnmarshalBinary(t *testing.T) { + u := UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} + b1 := []byte{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} + + u1 := UUID{} + err := u1.UnmarshalBinary(b1) + if err != nil { + t.Errorf("Error unmarshaling UUID: %s", err) + } + + if !Equal(u, u1) { + t.Errorf("UUIDs should be equal: %s and %s", u, u1) + } + + b2 := []byte{} + u2 := UUID{} + + err = u2.UnmarshalBinary(b2) + if err == nil { + t.Errorf("Should return error unmarshalling from empty byte slice, got %s", err) + } +} + +func TestFromString(t *testing.T) { + u := UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} + + s1 := "6ba7b810-9dad-11d1-80b4-00c04fd430c8" + s2 := "{6ba7b810-9dad-11d1-80b4-00c04fd430c8}" + s3 := "urn:uuid:6ba7b810-9dad-11d1-80b4-00c04fd430c8" + + _, err := FromString("") + if err == nil { + t.Errorf("Should return error trying to parse empty string, got %s", err) + } + + u1, err := FromString(s1) + if err != nil { + t.Errorf("Error parsing UUID from string: %s", err) + } + + if !Equal(u, u1) { + t.Errorf("UUIDs should be equal: %s and %s", u, u1) + } + + u2, err := FromString(s2) + if err != nil { + t.Errorf("Error parsing UUID from string: %s", err) + } + + if !Equal(u, u2) { + t.Errorf("UUIDs should be equal: %s and %s", u, u2) + } + + u3, err := FromString(s3) + if err != nil { + t.Errorf("Error parsing UUID from string: %s", err) + } + + if !Equal(u, u3) { + t.Errorf("UUIDs should be equal: %s and %s", u, u3) + } +} + +func TestFromStringShort(t *testing.T) { + // Invalid 35-character UUID string + s1 := "6ba7b810-9dad-11d1-80b4-00c04fd430c" + + for i := len(s1); i >= 0; i-- { + _, err := FromString(s1[:i]) + if err == nil { + t.Errorf("Should return error trying to parse too short string, got %s", err) + } + } +} + +func TestFromStringLong(t *testing.T) { + // Invalid 37+ character UUID string + s := []string{ + "6ba7b810-9dad-11d1-80b4-00c04fd430c8=", + "6ba7b810-9dad-11d1-80b4-00c04fd430c8}", + "{6ba7b810-9dad-11d1-80b4-00c04fd430c8}f", + "6ba7b810-9dad-11d1-80b4-00c04fd430c800c04fd430c8", + } + + for _, str := range s { + _, err := FromString(str) + if err == nil { + t.Errorf("Should return error trying to parse too long string, passed %s", str) + } + } +} + +func TestFromStringInvalid(t *testing.T) { + // Invalid UUID string formats + s := []string{ + "6ba7b8109dad11d180b400c04fd430c8", + "6ba7b8109dad11d180b400c04fd430c86ba7b8109dad11d180b400c04fd430c8", + "urn:uuid:{6ba7b810-9dad-11d1-80b4-00c04fd430c8}", + "6ba7b8109-dad-11d1-80b4-00c04fd430c8", + "6ba7b810-9dad1-1d1-80b4-00c04fd430c8", + "6ba7b810-9dad-11d18-0b4-00c04fd430c8", + "6ba7b810-9dad-11d1-80b40-0c04fd430c8", + "6ba7b810+9dad+11d1+80b4+00c04fd430c8", + "6ba7b810-9dad11d180b400c04fd430c8", + "6ba7b8109dad-11d180b400c04fd430c8", + "6ba7b8109dad11d1-80b400c04fd430c8", + "6ba7b8109dad11d180b4-00c04fd430c8", + } + + for _, str := range s { + _, err := FromString(str) + if err == nil { + t.Errorf("Should return error trying to parse invalid string, passed %s", str) + } + } +} + +func TestFromStringOrNil(t *testing.T) { + u := FromStringOrNil("") + if u != Nil { + t.Errorf("Should return Nil UUID on parse failure, got %s", u) + } +} + +func TestFromBytesOrNil(t *testing.T) { + b := []byte{} + u := FromBytesOrNil(b) + if u != Nil { + t.Errorf("Should return Nil UUID on parse failure, got %s", u) + } +} + +func TestMarshalText(t *testing.T) { + u := UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} + b1 := []byte("6ba7b810-9dad-11d1-80b4-00c04fd430c8") + + b2, err := u.MarshalText() + if err != nil { + t.Errorf("Error marshaling UUID: %s", err) + } + + if !bytes.Equal(b1, b2) { + t.Errorf("Marshaled UUID should be %s, got %s", b1, b2) + } +} + +func TestUnmarshalText(t *testing.T) { + u := UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} + b1 := []byte("6ba7b810-9dad-11d1-80b4-00c04fd430c8") + + u1 := UUID{} + err := u1.UnmarshalText(b1) + if err != nil { + t.Errorf("Error unmarshaling UUID: %s", err) + } + + if !Equal(u, u1) { + t.Errorf("UUIDs should be equal: %s and %s", u, u1) + } + + b2 := []byte("") + u2 := UUID{} + + err = u2.UnmarshalText(b2) + if err == nil { + t.Errorf("Should return error trying to unmarshal from empty string") + } +} + +func TestValue(t *testing.T) { + u, err := FromString("6ba7b810-9dad-11d1-80b4-00c04fd430c8") + if err != nil { + t.Errorf("Error parsing UUID from string: %s", err) + } + + val, err := u.Value() + if err != nil { + t.Errorf("Error getting UUID value: %s", err) + } + + if val != u.String() { + t.Errorf("Wrong value returned, should be equal: %s and %s", val, u) + } +} + +func TestValueNil(t *testing.T) { + u := UUID{} + + val, err := u.Value() + if err != nil { + t.Errorf("Error getting UUID value: %s", err) + } + + if val != Nil.String() { + t.Errorf("Wrong value returned, should be equal to UUID.Nil: %s", val) + } +} + +func TestNullUUIDValueNil(t *testing.T) { + u := NullUUID{} + + val, err := u.Value() + if err != nil { + t.Errorf("Error getting UUID value: %s", err) + } + + if val != nil { + t.Errorf("Wrong value returned, should be nil: %s", val) + } +} + +func TestScanBinary(t *testing.T) { + u := UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} + b1 := []byte{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} + + u1 := UUID{} + err := u1.Scan(b1) + if err != nil { + t.Errorf("Error unmarshaling UUID: %s", err) + } + + if !Equal(u, u1) { + t.Errorf("UUIDs should be equal: %s and %s", u, u1) + } + + b2 := []byte{} + u2 := UUID{} + + err = u2.Scan(b2) + if err == nil { + t.Errorf("Should return error unmarshalling from empty byte slice, got %s", err) + } +} + +func TestScanString(t *testing.T) { + u := UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} + s1 := "6ba7b810-9dad-11d1-80b4-00c04fd430c8" + + u1 := UUID{} + err := u1.Scan(s1) + if err != nil { + t.Errorf("Error unmarshaling UUID: %s", err) + } + + if !Equal(u, u1) { + t.Errorf("UUIDs should be equal: %s and %s", u, u1) + } + + s2 := "" + u2 := UUID{} + + err = u2.Scan(s2) + if err == nil { + t.Errorf("Should return error trying to unmarshal from empty string") + } +} + +func TestScanText(t *testing.T) { + u := UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} + b1 := []byte("6ba7b810-9dad-11d1-80b4-00c04fd430c8") + + u1 := UUID{} + err := u1.Scan(b1) + if err != nil { + t.Errorf("Error unmarshaling UUID: %s", err) + } + + if !Equal(u, u1) { + t.Errorf("UUIDs should be equal: %s and %s", u, u1) + } + + b2 := []byte("") + u2 := UUID{} + + err = u2.Scan(b2) + if err == nil { + t.Errorf("Should return error trying to unmarshal from empty string") + } +} + +func TestScanUnsupported(t *testing.T) { + u := UUID{} + + err := u.Scan(true) + if err == nil { + t.Errorf("Should return error trying to unmarshal from bool") + } +} + +func TestScanNil(t *testing.T) { + u := UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} + + err := u.Scan(nil) + if err == nil { + t.Errorf("Error UUID shouldn't allow unmarshalling from nil") + } +} + +func TestNullUUIDScanValid(t *testing.T) { + u := UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} + s1 := "6ba7b810-9dad-11d1-80b4-00c04fd430c8" + + u1 := NullUUID{} + err := u1.Scan(s1) + if err != nil { + t.Errorf("Error unmarshaling NullUUID: %s", err) + } + + if !u1.Valid { + t.Errorf("NullUUID should be valid") + } + + if !Equal(u, u1.UUID) { + t.Errorf("UUIDs should be equal: %s and %s", u, u1.UUID) + } +} + +func TestNullUUIDScanNil(t *testing.T) { + u := NullUUID{UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8}, true} + + err := u.Scan(nil) + if err != nil { + t.Errorf("Error unmarshaling NullUUID: %s", err) + } + + if u.Valid { + t.Errorf("NullUUID should not be valid") + } + + if !Equal(u.UUID, Nil) { + t.Errorf("NullUUID value should be equal to Nil: %s", u) + } +} + +func TestNewV1(t *testing.T) { + u := NewV1() + + if u.Version() != 1 { + t.Errorf("UUIDv1 generated with incorrect version: %d", u.Version()) + } + + if u.Variant() != VariantRFC4122 { + t.Errorf("UUIDv1 generated with incorrect variant: %d", u.Variant()) + } + + u1 := NewV1() + u2 := NewV1() + + if Equal(u1, u2) { + t.Errorf("UUIDv1 generated two equal UUIDs: %s and %s", u1, u2) + } + + oldFunc := epochFunc + epochFunc = func() uint64 { return 0 } + + u3 := NewV1() + u4 := NewV1() + + if Equal(u3, u4) { + t.Errorf("UUIDv1 generated two equal UUIDs: %s and %s", u3, u4) + } + + epochFunc = oldFunc +} + +func TestNewV2(t *testing.T) { + u1 := NewV2(DomainPerson) + + if u1.Version() != 2 { + t.Errorf("UUIDv2 generated with incorrect version: %d", u1.Version()) + } + + if u1.Variant() != VariantRFC4122 { + t.Errorf("UUIDv2 generated with incorrect variant: %d", u1.Variant()) + } + + u2 := NewV2(DomainGroup) + + if u2.Version() != 2 { + t.Errorf("UUIDv2 generated with incorrect version: %d", u2.Version()) + } + + if u2.Variant() != VariantRFC4122 { + t.Errorf("UUIDv2 generated with incorrect variant: %d", u2.Variant()) + } +} + +func TestNewV3(t *testing.T) { + u := NewV3(NamespaceDNS, "www.example.com") + + if u.Version() != 3 { + t.Errorf("UUIDv3 generated with incorrect version: %d", u.Version()) + } + + if u.Variant() != VariantRFC4122 { + t.Errorf("UUIDv3 generated with incorrect variant: %d", u.Variant()) + } + + if u.String() != "5df41881-3aed-3515-88a7-2f4a814cf09e" { + t.Errorf("UUIDv3 generated incorrectly: %s", u.String()) + } + + u = NewV3(NamespaceDNS, "python.org") + + if u.String() != "6fa459ea-ee8a-3ca4-894e-db77e160355e" { + t.Errorf("UUIDv3 generated incorrectly: %s", u.String()) + } + + u1 := NewV3(NamespaceDNS, "golang.org") + u2 := NewV3(NamespaceDNS, "golang.org") + if !Equal(u1, u2) { + t.Errorf("UUIDv3 generated different UUIDs for same namespace and name: %s and %s", u1, u2) + } + + u3 := NewV3(NamespaceDNS, "example.com") + if Equal(u1, u3) { + t.Errorf("UUIDv3 generated same UUIDs for different names in same namespace: %s and %s", u1, u2) + } + + u4 := NewV3(NamespaceURL, "golang.org") + if Equal(u1, u4) { + t.Errorf("UUIDv3 generated same UUIDs for sane names in different namespaces: %s and %s", u1, u4) + } +} + +func TestNewV4(t *testing.T) { + u := NewV4() + + if u.Version() != 4 { + t.Errorf("UUIDv4 generated with incorrect version: %d", u.Version()) + } + + if u.Variant() != VariantRFC4122 { + t.Errorf("UUIDv4 generated with incorrect variant: %d", u.Variant()) + } +} + +func TestNewV5(t *testing.T) { + u := NewV5(NamespaceDNS, "www.example.com") + + if u.Version() != 5 { + t.Errorf("UUIDv5 generated with incorrect version: %d", u.Version()) + } + + if u.Variant() != VariantRFC4122 { + t.Errorf("UUIDv5 generated with incorrect variant: %d", u.Variant()) + } + + u = NewV5(NamespaceDNS, "python.org") + + if u.String() != "886313e1-3b8a-5372-9b90-0c9aee199e5d" { + t.Errorf("UUIDv5 generated incorrectly: %s", u.String()) + } + + u1 := NewV5(NamespaceDNS, "golang.org") + u2 := NewV5(NamespaceDNS, "golang.org") + if !Equal(u1, u2) { + t.Errorf("UUIDv5 generated different UUIDs for same namespace and name: %s and %s", u1, u2) + } + + u3 := NewV5(NamespaceDNS, "example.com") + if Equal(u1, u3) { + t.Errorf("UUIDv5 generated same UUIDs for different names in same namespace: %s and %s", u1, u2) + } + + u4 := NewV5(NamespaceURL, "golang.org") + if Equal(u1, u4) { + t.Errorf("UUIDv3 generated same UUIDs for sane names in different namespaces: %s and %s", u1, u4) + } +} diff --git a/vendor/vendor.json b/vendor/vendor.json deleted file mode 100644 index dca08787..00000000 --- a/vendor/vendor.json +++ /dev/null @@ -1,555 +0,0 @@ -{ - "comment": "", - "ignore": "test", - "package": [ - { - "checksumSHA1": "o/3cn04KAiwC7NqNVvmfVTD+hgA=", - "path": "github.com/Microsoft/go-winio", - "revision": "78439966b38d69bf38227fbf57ac8a6fee70f69a", - "revisionTime": "2017-08-04T20:09:54Z" - }, - { - "checksumSHA1": "W5qMYydPUfwKPyvbgSfF7YSAx6w=", - "path": "github.com/btcsuite/btcd/btcec", - "revision": "1bdb71328511a5225d6300c3c08a79172f667996", - "revisionTime": "2016-07-09T19:04:59Z" - }, - { - "checksumSHA1": "Gj+xR1VgFKKmFXYOJMnAczC3Znk=", - "path": "github.com/docker/distribution/digestset", - "revision": "7a8efe719e55bbfaff7bc5718cdf0ed51ca821df", - "revisionTime": "2017-08-04T19:10:18Z" - }, - { - "checksumSHA1": "2Fe4D6PGaVE2he4fUeenLmhC1lE=", - "path": "github.com/docker/distribution/reference", - "revision": "7a8efe719e55bbfaff7bc5718cdf0ed51ca821df", - "revisionTime": "2017-08-04T19:10:18Z" - }, - { - "checksumSHA1": "XyK3nE86q9ek+9jiypeunC25o0M=", - "path": "github.com/docker/docker/api", - "revision": "202cf001dd7e6ca6c171aa52f454cc7b10f865bf", - "revisionTime": "2017-08-07T23:54:05Z" - }, - { - "checksumSHA1": "DmVjBB1a8uZzckWdWIu7pXWVTUc=", - "path": "github.com/docker/docker/api/types", - "revision": "202cf001dd7e6ca6c171aa52f454cc7b10f865bf", - "revisionTime": "2017-08-07T23:54:05Z" - }, - { - "checksumSHA1": "jVJDbe0IcyjoKc2xbohwzQr+FF0=", - "path": "github.com/docker/docker/api/types/blkiodev", - "revision": "202cf001dd7e6ca6c171aa52f454cc7b10f865bf", - "revisionTime": "2017-08-07T23:54:05Z" - }, - { - "checksumSHA1": "AeSC0BOu1uapkGqfSXtfVSpwJzs=", - "path": "github.com/docker/docker/api/types/container", - "revision": "202cf001dd7e6ca6c171aa52f454cc7b10f865bf", - "revisionTime": "2017-08-07T23:54:05Z" - }, - { - "checksumSHA1": "XDP7i6sMYGnUKeFzgt+mFBJwjjw=", - "path": "github.com/docker/docker/api/types/events", - "revision": "202cf001dd7e6ca6c171aa52f454cc7b10f865bf", - "revisionTime": "2017-08-07T23:54:05Z" - }, - { - "checksumSHA1": "J2OKngfI3vgswudr9PZVUFcRRu0=", - "path": "github.com/docker/docker/api/types/filters", - "revision": "202cf001dd7e6ca6c171aa52f454cc7b10f865bf", - "revisionTime": "2017-08-07T23:54:05Z" - }, - { - "checksumSHA1": "yeB781yxPhnN6OXQ9/qSsyih3ek=", - "path": "github.com/docker/docker/api/types/image", - "revision": "202cf001dd7e6ca6c171aa52f454cc7b10f865bf", - "revisionTime": "2017-08-07T23:54:05Z" - }, - { - "checksumSHA1": "euB/9WeNBA8r1siHY4seCkRBBng=", - "path": "github.com/docker/docker/api/types/mount", - "revision": "202cf001dd7e6ca6c171aa52f454cc7b10f865bf", - "revisionTime": "2017-08-07T23:54:05Z" - }, - { - "checksumSHA1": "Gskp+nvbVe8Gk1xPLHylZvNmqTg=", - "path": "github.com/docker/docker/api/types/network", - "revision": "202cf001dd7e6ca6c171aa52f454cc7b10f865bf", - "revisionTime": "2017-08-07T23:54:05Z" - }, - { - "checksumSHA1": "r2vWq7Uc3ExKzMqYgH0b4AKjLKY=", - "path": "github.com/docker/docker/api/types/registry", - "revision": "202cf001dd7e6ca6c171aa52f454cc7b10f865bf", - "revisionTime": "2017-08-07T23:54:05Z" - }, - { - "checksumSHA1": "VTxWyFud/RedrpllGdQonVtGM/A=", - "path": "github.com/docker/docker/api/types/strslice", - "revision": "202cf001dd7e6ca6c171aa52f454cc7b10f865bf", - "revisionTime": "2017-08-07T23:54:05Z" - }, - { - "checksumSHA1": "WNhyKx+2cJ5Gx3jdCeDr0J43F3Y=", - "path": "github.com/docker/docker/api/types/swarm", - "revision": "202cf001dd7e6ca6c171aa52f454cc7b10f865bf", - "revisionTime": "2017-08-07T23:54:05Z" - }, - { - "checksumSHA1": "mi8EDCDjtrZEONRXPG7VHJosDwY=", - "path": "github.com/docker/docker/api/types/swarm/runtime", - "revision": "202cf001dd7e6ca6c171aa52f454cc7b10f865bf", - "revisionTime": "2017-08-07T23:54:05Z" - }, - { - "checksumSHA1": "B7ZwKzrv3t3Vlox6/bYMHhMjsM8=", - "path": "github.com/docker/docker/api/types/time", - "revision": "202cf001dd7e6ca6c171aa52f454cc7b10f865bf", - "revisionTime": "2017-08-07T23:54:05Z" - }, - { - "checksumSHA1": "uDPQ3nHsrvGQc9tg/J9OSC4N5dQ=", - "path": "github.com/docker/docker/api/types/versions", - "revision": "202cf001dd7e6ca6c171aa52f454cc7b10f865bf", - "revisionTime": "2017-08-07T23:54:05Z" - }, - { - "checksumSHA1": "IBJy2zPEnYmcFJ3lM1eiRWnCxTA=", - "path": "github.com/docker/docker/api/types/volume", - "revision": "202cf001dd7e6ca6c171aa52f454cc7b10f865bf", - "revisionTime": "2017-08-07T23:54:05Z" - }, - { - "checksumSHA1": "jsjQr20W2W6Gewf8Un3D8IKu2I8=", - "path": "github.com/docker/docker/pkg/ioutils", - "revision": "202cf001dd7e6ca6c171aa52f454cc7b10f865bf", - "revisionTime": "2017-08-07T23:54:05Z" - }, - { - "checksumSHA1": "ndnAFCfsGC3upNQ6jAEwzxcurww=", - "path": "github.com/docker/docker/pkg/longpath", - "revision": "202cf001dd7e6ca6c171aa52f454cc7b10f865bf", - "revisionTime": "2017-08-07T23:54:05Z" - }, - { - "checksumSHA1": "OftwMeqd/CPdOXNrCD99oKui8YE=", - "path": "github.com/docker/docker/pkg/mount", - "revision": "202cf001dd7e6ca6c171aa52f454cc7b10f865bf", - "revisionTime": "2017-08-07T23:54:05Z" - }, - { - "checksumSHA1": "Aa2l7tUYFCEvHd+C//15fQnAfqQ=", - "path": "github.com/docker/docker/pkg/system", - "revision": "202cf001dd7e6ca6c171aa52f454cc7b10f865bf", - "revisionTime": "2017-08-07T23:54:05Z" - }, - { - "checksumSHA1": "ZLK19eBuLoOIEE92Dwxx6qHHxDI=", - "path": "github.com/docker/docker/pkg/tlsconfig", - "revision": "202cf001dd7e6ca6c171aa52f454cc7b10f865bf", - "revisionTime": "2017-08-07T23:54:05Z" - }, - { - "checksumSHA1": "JbiWTzH699Sqz25XmDlsARpMN9w=", - "path": "github.com/docker/go-connections/nat", - "revision": "3ede32e2033de7505e6500d6c868c2b9ed9f169d", - "revisionTime": "2017-06-23T20:36:43Z" - }, - { - "checksumSHA1": "jUfDG3VQsA2UZHvvIXncgiddpYA=", - "path": "github.com/docker/go-connections/sockets", - "revision": "3ede32e2033de7505e6500d6c868c2b9ed9f169d", - "revisionTime": "2017-06-23T20:36:43Z" - }, - { - "checksumSHA1": "c6lDGNwTm5mYq18IHP+lqYpk8xU=", - "path": "github.com/docker/go-connections/tlsconfig", - "revision": "3ede32e2033de7505e6500d6c868c2b9ed9f169d", - "revisionTime": "2017-06-23T20:36:43Z" - }, - { - "checksumSHA1": "UmXGieuTJQOzJPspPJTVKKKMiUA=", - "path": "github.com/docker/go-units", - "revision": "0dadbb0345b35ec7ef35e228dabb8de89a65bf52", - "revisionTime": "2017-01-27T09:51:30Z" - }, - { - "checksumSHA1": "sNAU9ojYVUhO6dVXey6T3JhRQpw=", - "path": "github.com/docker/libtrust", - "revision": "aabc10ec26b754e797f9028f4589c5b7bd90dc20", - "revisionTime": "2016-07-08T17:25:13Z" - }, - { - "checksumSHA1": "/Y/IvLkd3hSX1h3PDMHkkCBwK+4=", - "path": "github.com/ethereum/go-ethereum/common", - "revision": "431cf2a1e453346bcc627ac1fb9df3950a6c3499", - "revisionTime": "2017-06-16T14:11:54Z" - }, - { - "checksumSHA1": "NIN7nslnw4fUJlVcuxf5anvxAKQ=", - "path": "github.com/ethereum/go-ethereum/common/hexutil", - "revision": "431cf2a1e453346bcc627ac1fb9df3950a6c3499", - "revisionTime": "2017-06-16T14:11:54Z" - }, - { - "checksumSHA1": "Hd1Y5DkzYULQzJlSgYv2w5SiEAo=", - "path": "github.com/ethereum/go-ethereum/common/math", - "revision": "431cf2a1e453346bcc627ac1fb9df3950a6c3499", - "revisionTime": "2017-06-16T14:11:54Z" - }, - { - "checksumSHA1": "rofYNlEqnMen5Lg1N2+VcihuaIU=", - "path": "github.com/ethereum/go-ethereum/crypto", - "revision": "431cf2a1e453346bcc627ac1fb9df3950a6c3499", - "revisionTime": "2017-06-16T14:11:54Z" - }, - { - "checksumSHA1": "VsqOiLFDRSDa67wPeqlxKJmE0XE=", - "path": "github.com/ethereum/go-ethereum/crypto/secp256k1", - "revision": "431cf2a1e453346bcc627ac1fb9df3950a6c3499", - "revisionTime": "2017-06-16T14:11:54Z" - }, - { - "checksumSHA1": "yunX3AjO6JiMz0NSY/krvG3VWsk=", - "path": "github.com/ethereum/go-ethereum/crypto/sha3", - "revision": "431cf2a1e453346bcc627ac1fb9df3950a6c3499", - "revisionTime": "2017-06-16T14:11:54Z" - }, - { - "checksumSHA1": "CXoPEShhsjec6AmfyC6h5Ym8j18=", - "path": "github.com/ethereum/go-ethereum/ethdb", - "revision": "693d9ccbfbbcf7c32d3ff9fd8a432941e129a4ac", - "revisionTime": "2017-06-20T16:26:09Z" - }, - { - "checksumSHA1": "O56Cc6a0S2pK0oO9wZYO71xXeRM=", - "path": "github.com/ethereum/go-ethereum/event", - "revision": "693d9ccbfbbcf7c32d3ff9fd8a432941e129a4ac", - "revisionTime": "2017-06-20T16:26:09Z" - }, - { - "checksumSHA1": "NbRntdNRuwam0wGGNJ6HrR83P0M=", - "path": "github.com/ethereum/go-ethereum/log", - "revision": "431cf2a1e453346bcc627ac1fb9df3950a6c3499", - "revisionTime": "2017-06-16T14:11:54Z" - }, - { - "checksumSHA1": "LnUcnRFuZD3J8fsevk5kAJ+DlmU=", - "path": "github.com/ethereum/go-ethereum/metrics", - "revision": "693d9ccbfbbcf7c32d3ff9fd8a432941e129a4ac", - "revisionTime": "2017-06-20T16:26:09Z" - }, - { - "checksumSHA1": "dsD/vq8IdIgaiJJTfRnwKjF35oE=", - "path": "github.com/ethereum/go-ethereum/params", - "revision": "431cf2a1e453346bcc627ac1fb9df3950a6c3499", - "revisionTime": "2017-06-16T14:11:54Z" - }, - { - "checksumSHA1": "QARWkeJSFKOQF+/ryq6vqNmN8Q8=", - "path": "github.com/ethereum/go-ethereum/rlp", - "revision": "431cf2a1e453346bcc627ac1fb9df3950a6c3499", - "revisionTime": "2017-06-16T14:11:54Z" - }, - { - "checksumSHA1": "320PHjE15MUavTek9x6qojwQf7s=", - "path": "github.com/ethereum/go-ethereum/rpc", - "revision": "693d9ccbfbbcf7c32d3ff9fd8a432941e129a4ac", - "revisionTime": "2017-06-20T16:26:09Z" - }, - { - "checksumSHA1": "FdPv4Z5zhexDUEQDUDAnCQIKXnI=", - "path": "github.com/ethereum/go-ethereum/trie", - "revision": "431cf2a1e453346bcc627ac1fb9df3950a6c3499", - "revisionTime": "2017-06-16T14:11:54Z" - }, - { - "checksumSHA1": "tZVtZ5Zm7Q9AtARo7xfYh28ELXI=", - "path": "github.com/getamis/go-ethereum/common", - "revision": "57750cbf051bb25fce769f3f4869eb216672f22f", - "revisionTime": "2017-06-19T05:54:01Z", - "version": "=feature/pbft", - "versionExact": "feature/pbft" - }, - { - "checksumSHA1": "YvypTMzv0Ec9C9iwOCIRbBcl9XY=", - "path": "github.com/getamis/go-ethereum/common/hexutil", - "revision": "57750cbf051bb25fce769f3f4869eb216672f22f", - "revisionTime": "2017-06-19T05:54:01Z", - "version": "=feature/pbft", - "versionExact": "feature/pbft" - }, - { - "checksumSHA1": "kSu3LWnvEXHTgSH9KB3Q/eGAHAk=", - "path": "github.com/getamis/go-ethereum/core", - "revision": "431cf2a1e453346bcc627ac1fb9df3950a6c3499", - "revisionTime": "2017-06-16T14:11:54Z" - }, - { - "checksumSHA1": "xCsTCsFLsh4eJhcOXQfaIWQxtKo=", - "path": "github.com/getamis/go-ethereum/core/types", - "revision": "57750cbf051bb25fce769f3f4869eb216672f22f", - "revisionTime": "2017-06-19T05:54:01Z", - "version": "=feature/pbft", - "versionExact": "feature/pbft" - }, - { - "checksumSHA1": "ovKUpgF7FRdoZ+7ojAtKlUcBn/Q=", - "path": "github.com/getamis/go-ethereum/params", - "revision": "431cf2a1e453346bcc627ac1fb9df3950a6c3499", - "revisionTime": "2017-06-16T14:11:54Z" - }, - { - "checksumSHA1": "602c64HqPYM1v7dRjkFHEKxYinM=", - "path": "github.com/getamis/go-ethereum/rlp", - "revision": "57750cbf051bb25fce769f3f4869eb216672f22f", - "revisionTime": "2017-06-19T05:54:01Z", - "version": "=feature/pbft", - "versionExact": "feature/pbft" - }, - { - "checksumSHA1": "VcLNrvCcnZuSnebTxMRyNtzY3ZY=", - "path": "github.com/go-stack/stack", - "revision": "7a2f19628aabfe68f0766b59e74d6315f8347d22", - "revisionTime": "2017-05-04T03:43:18Z" - }, - { - "checksumSHA1": "haZp9uoO6N2UX4RwEtnlm9nR/AU=", - "path": "github.com/gogo/protobuf/proto", - "revision": "1c2b16bc280d6635de6c52fc1471ab962dc36ec9", - "revisionTime": "2017-08-08T05:47:17Z" - }, - { - "checksumSHA1": "p/8vSviYF91gFflhrt5vkyksroo=", - "path": "github.com/golang/snappy", - "revision": "553a641470496b2327abcac10b36396bd98e45c9", - "revisionTime": "2017-02-15T23:32:05Z" - }, - { - "checksumSHA1": "d9PxF1XQGLMJZRct2R8qVM/eYlE=", - "path": "github.com/hashicorp/golang-lru", - "revision": "0a025b7e63adc15a622f29b0b2c4c3848243bbf6", - "revisionTime": "2016-08-13T22:13:03Z" - }, - { - "checksumSHA1": "9hffs0bAIU6CquiRhKQdzjHnKt0=", - "path": "github.com/hashicorp/golang-lru/simplelru", - "revision": "0a025b7e63adc15a622f29b0b2c4c3848243bbf6", - "revisionTime": "2016-08-13T22:13:03Z" - }, - { - "checksumSHA1": "NBPHJLGwUSAVVpz1I++Rb0iAsGg=", - "path": "github.com/moby/moby/client", - "revision": "202cf001dd7e6ca6c171aa52f454cc7b10f865bf", - "revisionTime": "2017-08-07T23:54:05Z" - }, - { - "checksumSHA1": "A6nZdZ1/lTOVINhIndyw2ZWN9JU=", - "path": "github.com/naoina/go-stringutil", - "revision": "6b638e95a32d0c1131db0e7fe83775cbea4a0d0b", - "revisionTime": "2015-11-18T23:44:43Z" - }, - { - "checksumSHA1": "2w8GeWfyeUrrVyj5MitxcHhaO7s=", - "path": "github.com/naoina/toml", - "revision": "e6f5723bf2a66af014955e0888881314cf294129", - "revisionTime": "2017-04-28T05:41:52Z" - }, - { - "checksumSHA1": "xZBlSMT5o/A+EDOro6KbfHZwSNc=", - "path": "github.com/naoina/toml/ast", - "revision": "e6f5723bf2a66af014955e0888881314cf294129", - "revisionTime": "2017-04-28T05:41:52Z" - }, - { - "checksumSHA1": "OFNit1Qx2DdWhotfREKodDNUwCM=", - "path": "github.com/opencontainers/go-digest", - "revision": "279bed98673dd5bef374d3b6e4b09e2af76183bf", - "revisionTime": "2017-06-07T19:53:33Z" - }, - { - "checksumSHA1": "ZGlIwSRjdLYCUII7JLE++N4w7Xc=", - "path": "github.com/opencontainers/image-spec/specs-go", - "revision": "710038243d857231f17df1c3f4c10850154bd1f7", - "revisionTime": "2017-07-31T13:49:31Z" - }, - { - "checksumSHA1": "jdbXRRzeu0njLE9/nCEZG+Yg/Jk=", - "path": "github.com/opencontainers/image-spec/specs-go/v1", - "revision": "710038243d857231f17df1c3f4c10850154bd1f7", - "revisionTime": "2017-07-31T13:49:31Z" - }, - { - "checksumSHA1": "rJab1YdNhQooDiBWNnt7TLWPyBU=", - "path": "github.com/pkg/errors", - "revision": "c605e284fe17294bda444b34710735b29d1a9d90", - "revisionTime": "2017-05-05T04:36:39Z" - }, - { - "checksumSHA1": "KAzbLjI9MzW2tjfcAsK75lVRp6I=", - "path": "github.com/rcrowley/go-metrics", - "revision": "1f30fe9094a513ce4c700b9a54458bbb0c96996c", - "revisionTime": "2016-11-28T21:05:44Z" - }, - { - "checksumSHA1": "q/d9nXRQYKEJ/EWn+5y6jL8rPGs=", - "path": "github.com/rcrowley/go-metrics/exp", - "revision": "1f30fe9094a513ce4c700b9a54458bbb0c96996c", - "revisionTime": "2016-11-28T21:05:44Z" - }, - { - "checksumSHA1": "lZmPAbekxLbMFQirB/vzbdI+5O8=", - "path": "github.com/rs/cors", - "revision": "8dd4211afb5d08dbb39a533b9bb9e4b486351df6", - "revisionTime": "2017-06-08T16:51:55Z" - }, - { - "checksumSHA1": "I5DMrLM0FpmvG81tAWZ3zoydBIo=", - "path": "github.com/sirupsen/logrus", - "revision": "181d419aa9e2223811b824e8f0b4af96f9ba9302", - "revisionTime": "2017-07-28T07:42:14Z" - }, - { - "checksumSHA1": "HcDa/j4eMiKGYEo8qmrW+2NDFcE=", - "path": "github.com/syndtr/goleveldb/leveldb", - "revision": "8c81ea47d4c41a385645e133e15510fc6a2a74b4", - "revisionTime": "2017-04-09T01:48:31Z" - }, - { - "checksumSHA1": "EKIow7XkgNdWvR/982ffIZxKG8Y=", - "path": "github.com/syndtr/goleveldb/leveldb/cache", - "revision": "8c81ea47d4c41a385645e133e15510fc6a2a74b4", - "revisionTime": "2017-04-09T01:48:31Z" - }, - { - "checksumSHA1": "5KPgnvCPlR0ysDAqo6jApzRQ3tw=", - "path": "github.com/syndtr/goleveldb/leveldb/comparer", - "revision": "8c81ea47d4c41a385645e133e15510fc6a2a74b4", - "revisionTime": "2017-04-09T01:48:31Z" - }, - { - "checksumSHA1": "1DRAxdlWzS4U0xKN/yQ/fdNN7f0=", - "path": "github.com/syndtr/goleveldb/leveldb/errors", - "revision": "8c81ea47d4c41a385645e133e15510fc6a2a74b4", - "revisionTime": "2017-04-09T01:48:31Z" - }, - { - "checksumSHA1": "eqKeD6DS7eNCtxVYZEHHRKkyZrw=", - "path": "github.com/syndtr/goleveldb/leveldb/filter", - "revision": "8c81ea47d4c41a385645e133e15510fc6a2a74b4", - "revisionTime": "2017-04-09T01:48:31Z" - }, - { - "checksumSHA1": "8dXuAVIsbtaMiGGuHjzGR6Ny/5c=", - "path": "github.com/syndtr/goleveldb/leveldb/iterator", - "revision": "8c81ea47d4c41a385645e133e15510fc6a2a74b4", - "revisionTime": "2017-04-09T01:48:31Z" - }, - { - "checksumSHA1": "gJY7bRpELtO0PJpZXgPQ2BYFJ88=", - "path": "github.com/syndtr/goleveldb/leveldb/journal", - "revision": "8c81ea47d4c41a385645e133e15510fc6a2a74b4", - "revisionTime": "2017-04-09T01:48:31Z" - }, - { - "checksumSHA1": "j+uaQ6DwJ50dkIdfMQu1TXdlQcY=", - "path": "github.com/syndtr/goleveldb/leveldb/memdb", - "revision": "8c81ea47d4c41a385645e133e15510fc6a2a74b4", - "revisionTime": "2017-04-09T01:48:31Z" - }, - { - "checksumSHA1": "UmQeotV+m8/FduKEfLOhjdp18rs=", - "path": "github.com/syndtr/goleveldb/leveldb/opt", - "revision": "8c81ea47d4c41a385645e133e15510fc6a2a74b4", - "revisionTime": "2017-04-09T01:48:31Z" - }, - { - "checksumSHA1": "tQ2AqXXAEy9icbZI9dLVdZGvWMw=", - "path": "github.com/syndtr/goleveldb/leveldb/storage", - "revision": "8c81ea47d4c41a385645e133e15510fc6a2a74b4", - "revisionTime": "2017-04-09T01:48:31Z" - }, - { - "checksumSHA1": "gWFPMz8OQeul0t54RM66yMTX49g=", - "path": "github.com/syndtr/goleveldb/leveldb/table", - "revision": "8c81ea47d4c41a385645e133e15510fc6a2a74b4", - "revisionTime": "2017-04-09T01:48:31Z" - }, - { - "checksumSHA1": "4zil8Gwg8VPkDn1YzlgCvtukJFU=", - "path": "github.com/syndtr/goleveldb/leveldb/util", - "revision": "8c81ea47d4c41a385645e133e15510fc6a2a74b4", - "revisionTime": "2017-04-09T01:48:31Z" - }, - { - "checksumSHA1": "y/oIaxq2d3WPizRZfVjo8RCRYTU=", - "path": "golang.org/x/crypto/ripemd160", - "revision": "adbae1b6b6fb4b02448a0fc0dbbc9ba2b95b294d", - "revisionTime": "2017-06-19T06:03:41Z" - }, - { - "checksumSHA1": "8wbHSD24FGJUJDS1F6wbtEt8z+w=", - "path": "golang.org/x/crypto/ssh/terminal", - "revision": "81db3efc71b576a04b145ca576c0bb9c0fb74d4f", - "revisionTime": "2017-07-29T20:27:48Z" - }, - { - "checksumSHA1": "dr5+PfIRzXeN+l1VG+s0lea9qz8=", - "path": "golang.org/x/net/context", - "revision": "945ddfdd3bb885ce838728b0169bf94ae76970c8", - "revisionTime": "2017-07-20T22:15:25Z" - }, - { - "checksumSHA1": "WHc3uByvGaMcnSoI21fhzYgbOgg=", - "path": "golang.org/x/net/context/ctxhttp", - "revision": "945ddfdd3bb885ce838728b0169bf94ae76970c8", - "revisionTime": "2017-07-20T22:15:25Z" - }, - { - "checksumSHA1": "QEm/dePZ0lOnyOs+m22KjXfJ/IU=", - "path": "golang.org/x/net/proxy", - "revision": "945ddfdd3bb885ce838728b0169bf94ae76970c8", - "revisionTime": "2017-07-20T22:15:25Z" - }, - { - "checksumSHA1": "7EZyXN0EmZLgGxZxK01IJua4c8o=", - "path": "golang.org/x/net/websocket", - "revision": "fe686d45ea04bc1bd4eff6a52865ce8757320325", - "revisionTime": "2017-06-18T05:18:41Z" - }, - { - "checksumSHA1": "fwb6FNBUs0SOyUpUx5R31Xf22GY=", - "path": "golang.org/x/sys/unix", - "revision": "d8f5ea21b9295e315e612b4bcf4bedea93454d4d", - "revisionTime": "2017-08-03T09:04:06Z" - }, - { - "checksumSHA1": "LkAsnLUlAZSg3lRYk7BEyNfog3A=", - "path": "golang.org/x/sys/windows", - "revision": "d8f5ea21b9295e315e612b4bcf4bedea93454d4d", - "revisionTime": "2017-08-03T09:04:06Z" - }, - { - "checksumSHA1": "NGg7/qIJVUfXi7xnEyyDLocdi6Y=", - "path": "gopkg.in/fatih/set.v0", - "revision": "27c40922c40b43fe04554d8223a402af3ea333f3", - "revisionTime": "2014-12-10T08:48:24Z" - }, - { - "checksumSHA1": "DQXNV0EivoHm4q+bkdahYXrjjfE=", - "path": "gopkg.in/karalabe/cookiejar.v2/collections/prque", - "revision": "8dcd6a7f4951f6ff3ee9cbb919a06d8925822e57", - "revisionTime": "2015-07-24T13:16:13Z" - }, - { - "checksumSHA1": "0xgs8lwcWLUffemlj+SsgKlxvDU=", - "path": "gopkg.in/natefinch/npipe.v2", - "revision": "c1b8fa8bdccecb0b8db834ee0b92fdbcfa606dd6", - "revisionTime": "2016-06-21T03:49:01Z" - } - ], - "rootPath": "github.com/getamis/istanbul-tools" -}