diff --git a/.gitignore b/.gitignore index 6d0587669..1924a7ae7 100644 --- a/.gitignore +++ b/.gitignore @@ -25,3 +25,4 @@ scripts/cutWALUntil/cutWALUntil *.iml libs/pubsub/query/fuzz_test/output +shunit2 diff --git a/Gopkg.lock b/Gopkg.lock index e45b84d13..f2390c376 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -13,6 +13,12 @@ packages = ["btcec"] revision = "86fed781132ac890ee03e906e4ecd5d6fa180c64" +[[projects]] + branch = "master" + name = "github.com/btcsuite/btcutil" + packages = ["base58"] + revision = "d4cc87b860166d00d6b5b9e0d3b3d71d6088d4d4" + [[projects]] name = "github.com/davecgh/go-spew" packages = ["spew"] @@ -26,10 +32,10 @@ revision = "95f809107225be108efcf10a3509e4ea6ceef3c4" [[projects]] + branch = "master" name = "github.com/fortytw2/leaktest" packages = ["."] - revision = "a5ef70473c97b71626b9abeda80ee92ba2a7de9e" - version = "v1.2.0" + revision = "b008db64ef8daabb22ff6daa557f33b41d8f6ccd" [[projects]] name = "github.com/fsnotify/fsnotify" @@ -306,14 +312,8 @@ [[projects]] name = "github.com/tendermint/go-amino" packages = ["."] - revision = "ed62928576cfcaf887209dc96142cd79cdfff389" - version = "0.9.9" - -[[projects]] - name = "github.com/tendermint/go-crypto" - packages = ["."] - revision = "915416979bf70efa4bcbf1c6cd5d64c5fff9fc19" - version = "v0.6.2" + revision = "2106ca61d91029c931fd54968c2bb02dc96b1412" + version = "0.10.1" [[projects]] name = "github.com/tendermint/tmlibs" @@ -336,7 +336,12 @@ branch = "master" name = "golang.org/x/crypto" packages = [ + "bcrypt", + "blowfish", + "chacha20poly1305", "curve25519", + "hkdf", + "internal/chacha20", "nacl/box", "nacl/secretbox", "openpgp/armor", @@ -364,7 +369,10 @@ [[projects]] branch = "master" name = "golang.org/x/sys" - packages = ["unix"] + packages = [ + "cpu", + "unix" + ] revision = "a9e25c09b96b8870693763211309e213c6ef299d" [[projects]] @@ -426,6 +434,6 @@ [solve-meta] analyzer-name = "dep" analyzer-version = 1 - inputs-digest = "3bd388e520a08cd0aa14df2d6f5ecb46449d7c36fd80cf52eb775798e6accbaa" + inputs-digest = "d17038089dd6383ff5028229d4026bb92f5c7adc7e9c1cd52584237e2e5fd431" solver-name = "gps-cdcl" solver-version = 1 diff --git a/Gopkg.toml b/Gopkg.toml index 13339e550..d9b381337 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -73,13 +73,9 @@ name = "github.com/tendermint/abci" version = "~0.12.0" -[[constraint]] - name = "github.com/tendermint/go-crypto" - version = "~0.6.2" - [[constraint]] name = "github.com/tendermint/go-amino" - version = "=0.9.9" + version = "~0.10.1" [[override]] name = "github.com/tendermint/tmlibs" diff --git a/Makefile b/Makefile old mode 100755 new mode 100644 diff --git a/README.md b/README.md index 52e93a7cd..c31c44dbe 100644 --- a/README.md +++ b/README.md @@ -74,7 +74,7 @@ Additional information about some - and eventually all - of the sub-projects bel * [ABCI](http://github.com/tendermint/abci), the Application Blockchain Interface * [Go-Wire](http://github.com/tendermint/go-wire), a deterministic serialization library -* [Go-Crypto](http://github.com/tendermint/go-crypto), an elliptic curve cryptography library +* [Go-Crypto](http://github.com/tendermint/tendermint/crypto), an elliptic curve cryptography library * [TmLibs](http://github.com/tendermint/tmlibs), an assortment of Go libraries used internally * [IAVL](http://github.com/tendermint/iavl), Merkleized IAVL+ Tree implementation diff --git a/benchmarks/codec_test.go b/benchmarks/codec_test.go index 9acafce71..ee61cc9a4 100644 --- a/benchmarks/codec_test.go +++ b/benchmarks/codec_test.go @@ -5,8 +5,8 @@ import ( "time" "github.com/tendermint/go-amino" - "github.com/tendermint/go-crypto" + "github.com/tendermint/tendermint/crypto" proto "github.com/tendermint/tendermint/benchmarks/proto" "github.com/tendermint/tendermint/p2p" ctypes "github.com/tendermint/tendermint/rpc/core/types" diff --git a/blockchain/store_test.go b/blockchain/store_test.go index a1bd0fd5d..1e0c223ad 100644 --- a/blockchain/store_test.go +++ b/blockchain/store_test.go @@ -29,7 +29,7 @@ func TestLoadBlockStoreStateJSON(t *testing.T) { func TestNewBlockStore(t *testing.T) { db := db.NewMemDB() - db.Set(blockStoreKey, []byte(`{"height": 10000}`)) + db.Set(blockStoreKey, []byte(`{"height": "10000"}`)) bs := NewBlockStore(db) require.Equal(t, int64(10000), bs.Height(), "failed to properly parse blockstore") diff --git a/blockchain/wire.go b/blockchain/wire.go index 55b4e60ae..70b50565d 100644 --- a/blockchain/wire.go +++ b/blockchain/wire.go @@ -2,7 +2,7 @@ package blockchain import ( "github.com/tendermint/go-amino" - "github.com/tendermint/go-crypto" + "github.com/tendermint/tendermint/crypto" ) var cdc = amino.NewCodec() diff --git a/cmd/priv_val_server/main.go b/cmd/priv_val_server/main.go index c78adeb82..ac7dd91ba 100644 --- a/cmd/priv_val_server/main.go +++ b/cmd/priv_val_server/main.go @@ -4,7 +4,7 @@ import ( "flag" "os" - crypto "github.com/tendermint/go-crypto" + crypto "github.com/tendermint/tendermint/crypto" cmn "github.com/tendermint/tmlibs/common" "github.com/tendermint/tmlibs/log" diff --git a/cmd/tendermint/commands/wire.go b/cmd/tendermint/commands/wire.go index 4c133a8c5..a09019133 100644 --- a/cmd/tendermint/commands/wire.go +++ b/cmd/tendermint/commands/wire.go @@ -2,7 +2,7 @@ package commands import ( "github.com/tendermint/go-amino" - "github.com/tendermint/go-crypto" + "github.com/tendermint/tendermint/crypto" ) var cdc = amino.NewCodec() diff --git a/config/config.go b/config/config.go index 6a283a82c..418638a60 100644 --- a/config/config.go +++ b/config/config.go @@ -279,8 +279,9 @@ type P2PConfig struct { // Time to wait before flushing messages out on the connection, in ms FlushThrottleTimeout int `mapstructure:"flush_throttle_timeout"` - // Maximum size of a message packet payload, in bytes - MaxPacketMsgPayloadSize int `mapstructure:"max_packet_msg_payload_size"` + // Maximum size of a message packet, in bytes + // Includes a header, which is ~13 bytes + MaxPacketMsgSize int `mapstructure:"max_packet_msg_size"` // Rate at which packets can be sent, in bytes/second SendRate int64 `mapstructure:"send_rate"` @@ -319,22 +320,22 @@ type P2PConfig struct { // DefaultP2PConfig returns a default configuration for the peer-to-peer layer func DefaultP2PConfig() *P2PConfig { return &P2PConfig{ - ListenAddress: "tcp://0.0.0.0:26656", - AddrBook: defaultAddrBookPath, - AddrBookStrict: true, - MaxNumPeers: 50, - FlushThrottleTimeout: 100, - MaxPacketMsgPayloadSize: 1024, // 1 kB - SendRate: 512000, // 500 kB/s - RecvRate: 512000, // 500 kB/s - PexReactor: true, - SeedMode: false, - AllowDuplicateIP: true, // so non-breaking yet - HandshakeTimeout: 20 * time.Second, - DialTimeout: 3 * time.Second, - TestDialFail: false, - TestFuzz: false, - TestFuzzConfig: DefaultFuzzConnConfig(), + ListenAddress: "tcp://0.0.0.0:26656", + AddrBook: defaultAddrBookPath, + AddrBookStrict: true, + MaxNumPeers: 50, + FlushThrottleTimeout: 100, + MaxPacketMsgSize: 1024, // 1 kB + SendRate: 512000, // 500 kB/s + RecvRate: 512000, // 500 kB/s + PexReactor: true, + SeedMode: false, + AllowDuplicateIP: true, // so non-breaking yet + HandshakeTimeout: 20 * time.Second, + DialTimeout: 3 * time.Second, + TestDialFail: false, + TestFuzz: false, + TestFuzzConfig: DefaultFuzzConnConfig(), } } diff --git a/config/toml.go b/config/toml.go index c3d41a9b7..0bf9d5315 100644 --- a/config/toml.go +++ b/config/toml.go @@ -147,8 +147,9 @@ flush_throttle_timeout = {{ .P2P.FlushThrottleTimeout }} # Maximum number of peers to connect to max_num_peers = {{ .P2P.MaxNumPeers }} -# Maximum size of a message packet payload, in bytes -max_packet_msg_payload_size = {{ .P2P.MaxPacketMsgPayloadSize }} +# Maximum size of a message packet, in bytes +# Includes a header, which is ~13 bytes +max_packet_msg_size = {{ .P2P.MaxPacketMsgSize }} # Rate at which packets can be sent, in bytes/second send_rate = {{ .P2P.SendRate }} @@ -298,10 +299,10 @@ var testGenesis = `{ "validators": [ { "pub_key": { - "type": "AC26791624DE60", + "type": "tendermint/PubKeyEd25519", "value":"AT/+aaL1eB0477Mud9JMm8Sh8BIvOYlPGC9KkIUmFaE=" }, - "power": 10, + "power": "10", "name": "" } ], @@ -309,16 +310,16 @@ var testGenesis = `{ }` var testPrivValidator = `{ - "address": "849CB2C877F87A20925F35D00AE6688342D25B47", + "address": "A3258DCBF45DCA0DF052981870F2D1441A36D145", "pub_key": { - "type": "AC26791624DE60", + "type": "tendermint/PubKeyEd25519", "value": "AT/+aaL1eB0477Mud9JMm8Sh8BIvOYlPGC9KkIUmFaE=" }, "priv_key": { - "type": "954568A3288910", + "type": "tendermint/PrivKeyEd25519", "value": "EVkqJO/jIXp3rkASXfh9YnyToYXRXhBr6g9cQVxPFnQBP/5povV4HTjvsy530kybxKHwEi85iU8YL0qQhSYVoQ==" }, - "last_height": 0, - "last_round": 0, + "last_height": "0", + "last_round": "0", "last_step": 0 }` diff --git a/consensus/replay_test.go b/consensus/replay_test.go index 725568ed5..927dfadca 100644 --- a/consensus/replay_test.go +++ b/consensus/replay_test.go @@ -18,7 +18,7 @@ import ( "github.com/tendermint/abci/example/kvstore" abci "github.com/tendermint/abci/types" - crypto "github.com/tendermint/go-crypto" + crypto "github.com/tendermint/tendermint/crypto" auto "github.com/tendermint/tmlibs/autofile" cmn "github.com/tendermint/tmlibs/common" dbm "github.com/tendermint/tmlibs/db" diff --git a/consensus/test_data/many_blocks.cswal b/consensus/test_data/many_blocks.cswal deleted file mode 100644 index d443fff78..000000000 Binary files a/consensus/test_data/many_blocks.cswal and /dev/null differ diff --git a/consensus/types/round_state_test.go b/consensus/types/round_state_test.go index dc88c3a13..042d8de7f 100644 --- a/consensus/types/round_state_test.go +++ b/consensus/types/round_state_test.go @@ -5,7 +5,7 @@ import ( "time" "github.com/tendermint/go-amino" - "github.com/tendermint/go-crypto" + "github.com/tendermint/tendermint/crypto" "github.com/tendermint/tendermint/types" cmn "github.com/tendermint/tmlibs/common" ) diff --git a/consensus/types/wire.go b/consensus/types/wire.go index bd5c4497d..6342d7eba 100644 --- a/consensus/types/wire.go +++ b/consensus/types/wire.go @@ -2,7 +2,7 @@ package types import ( "github.com/tendermint/go-amino" - "github.com/tendermint/go-crypto" + "github.com/tendermint/tendermint/crypto" ) var cdc = amino.NewCodec() diff --git a/consensus/wal_generator.go b/consensus/wal_generator.go index f61af15f5..9a4b70595 100644 --- a/consensus/wal_generator.go +++ b/consensus/wal_generator.go @@ -27,7 +27,7 @@ import ( // stripped down version of node (proxy app, event bus, consensus state) with a // persistent kvstore application and special consensus wal instance // (byteBufferWAL) and waits until numBlocks are created. Then it returns a WAL -// content. +// content. If the node fails to produce given numBlocks, it returns an error. func WALWithNBlocks(numBlocks int) (data []byte, err error) { config := getConfig() @@ -89,15 +89,15 @@ func WALWithNBlocks(numBlocks int) (data []byte, err error) { if err := consensusState.Start(); err != nil { return nil, errors.Wrap(err, "failed to start consensus state") } - defer consensusState.Stop() select { case <-numBlocksWritten: + consensusState.Stop() wr.Flush() return b.Bytes(), nil case <-time.After(1 * time.Minute): - wr.Flush() - return b.Bytes(), fmt.Errorf("waited too long for tendermint to produce %d blocks (grep logs for `wal_generator`)", numBlocks) + consensusState.Stop() + return []byte{}, fmt.Errorf("waited too long for tendermint to produce %d blocks (grep logs for `wal_generator`)", numBlocks) } } diff --git a/consensus/wire.go b/consensus/wire.go index 81223c689..5f231c0c7 100644 --- a/consensus/wire.go +++ b/consensus/wire.go @@ -2,7 +2,7 @@ package consensus import ( "github.com/tendermint/go-amino" - "github.com/tendermint/go-crypto" + "github.com/tendermint/tendermint/crypto" ) var cdc = amino.NewCodec() diff --git a/crypto/CHANGELOG.md b/crypto/CHANGELOG.md new file mode 100644 index 000000000..dd7c1039f --- /dev/null +++ b/crypto/CHANGELOG.md @@ -0,0 +1,154 @@ +# Changelog + +## 0.9.0 + +BREAKING CHANGES + +- `priv.PubKey()` no longer returns an error. Any applicable errors (such as when fetching the public key from a hardware wallet) should be checked and returned when constructing the private key. + +## 0.8.0 + +**TBD** + +## 0.7.0 + +**May 30th, 2018** + +BREAKING CHANGES + +No breaking changes compared to 0.6.2, but making up for the version bump that +should have happened in 0.6.1. + +We also bring in the `tmlibs/merkle` package with breaking changes: + +- change the hash function from RIPEMD160 to tmhash (first 20-bytes of SHA256) +- remove unused funcs and unexport SimpleMap + +FEATURES + +- [xchacha20poly1305] New authenticated encryption module +- [merkle] Moved in from tmlibs +- [merkle/tmhash] New hash function: the first 20-bytes of SHA256 + +IMPROVEMENTS + +- Remove some dead code +- Use constant-time compare for signatures + +BUG FIXES + +- Fix MixEntropy weakness +- Fix PrivKeyEd25519.Generate() + +## 0.6.2 (April 9, 2018) + +IMPROVEMENTS + +- Update for latest go-amino + +## 0.6.1 (March 26, 2018) + +BREAKING CHANGES + +- Encoding uses MarshalBinaryBare rather than MarshalBinary (which auto-length-prefixes) for pub/priv/sig. + +## 0.6.0 (March 2, 2018) + +BREAKING CHANGES + +- Update Amino names from "com.tendermint/..." to "tendermint/" + +## 0.5.0 (March 2, 2018) + +BREAKING CHANGES + +- nano: moved to `_nano` now while we're having build issues +- bcrypt: moved to `keys/bcrypt` +- hd: moved to `keys/hd`; `BTC` added to some function names; other function cleanup +- keys/cryptostore: moved to `keys`, renamed to `keybase`, and completely refactored +- keys: moved BIP39 related code to `keys/words` + +FEATURE + +- `Address` is a type alias for `cmn.HexBytes` + +BUG FIX + +- PrivKey comparisons done in constant time + +## 0.4.1 (October 27, 2017) + +This release removes support for bcrypt as it was merged too soon without an upgrade plan +for existing keys. + +REVERTS THE FOLLOWING COMMITS: + +- Parameterize and lower bcrypt cost - dfc4cdd2d71513e4a9922d679c74f36357c4c862 +- Upgrade keys to use bcrypt with salts (#38) - 8e7f0e7701f92206679ad093d013b9b162427631 + +## 0.4.0 (October 27, 2017) + +BREAKING CHANGES: + +- `keys`: use bcrypt plus salt + +FEATURES: + +- add support for signing via Ledger Nano + +IMPROVEMENTS: + +- linting and comments + +## 0.3.0 (September 22, 2017) + +BREAKING CHANGES: + +- Remove `cmd` and `keys/tx` packages altogether: move it to the cosmos-sdk +- `cryptostore.Generator` takes a secret +- Remove `String()` from `Signature` interface + +FEATURES: + +- `keys`: add CRC16 error correcting code + +IMPROVEMENTS: + +- Allow no passwords on keys for development convenience + + +## 0.2.1 (June 21, 2017) + +- Improve keys command + - No password prompts in non-interactive mode (echo 'foobar' | keys new foo) + - Added support for seed phrases + - Seed phrase now returned on `keys new` + - Add `keys restore` to restore private key from key phrase + - Checksum to verify typos in the seed phrase (rather than just a useless key) + - Add `keys delete` to remove a key if needed + +## 0.2.0 (May 18, 2017) + +BREAKING CHANGES: + +- [hd] The following functions no longer take a `coin string` as argument: `ComputeAddress`, `AddrFromPubKeyBytes`, `ComputeAddressForPrivKey`, `ComputeWIF`, `WIFFromPrivKeyBytes` +- Changes to `PrivKey`, `PubKey`, and `Signature` (denoted `Xxx` below): + - interfaces are renamed `XxxInner`, and are not for use outside the package, though they must be exposed for sake of serialization. + - `Xxx` is now a struct that wraps the corresponding `XxxInner` interface + +FEATURES: + +- `github.com/tendermint/go-keys -> github.com/tendermint/go-crypto/keys` - command and lib for generating and managing encrypted keys +- [hd] New function `WIFFromPrivKeyBytes(privKeyBytes []byte, compress bool) string` +- Changes to `PrivKey`, `PubKey`, and `Signature` (denoted `Xxx` below): + - Expose a new method `Unwrap() XxxInner` on the `Xxx` struct which returns the corresponding `XxxInner` interface + - Expose a new method `Wrap() Xxx` on the `XxxInner` interface which returns the corresponding `Xxx` struct + +IMPROVEMENTS: + +- Update to use new `tmlibs` repository + +## 0.1.0 (April 14, 2017) + +Initial release + diff --git a/crypto/Gopkg.lock b/crypto/Gopkg.lock new file mode 100644 index 000000000..7dbe6ae72 --- /dev/null +++ b/crypto/Gopkg.lock @@ -0,0 +1,137 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + branch = "master" + name = "github.com/btcsuite/btcd" + packages = ["btcec"] + revision = "86fed781132ac890ee03e906e4ecd5d6fa180c64" + +[[projects]] + branch = "master" + name = "github.com/btcsuite/btcutil" + packages = ["base58"] + revision = "d4cc87b860166d00d6b5b9e0d3b3d71d6088d4d4" + +[[projects]] + name = "github.com/davecgh/go-spew" + packages = ["spew"] + revision = "346938d642f2ec3594ed81d874461961cd0faa76" + version = "v1.1.0" + +[[projects]] + name = "github.com/go-kit/kit" + packages = [ + "log", + "log/level", + "log/term" + ] + revision = "4dc7be5d2d12881735283bcab7352178e190fc71" + version = "v0.6.0" + +[[projects]] + name = "github.com/go-logfmt/logfmt" + packages = ["."] + revision = "390ab7935ee28ec6b286364bba9b4dd6410cb3d5" + version = "v0.3.0" + +[[projects]] + name = "github.com/go-stack/stack" + packages = ["."] + revision = "259ab82a6cad3992b4e21ff5cac294ccb06474bc" + version = "v1.7.0" + +[[projects]] + name = "github.com/gogo/protobuf" + packages = [ + "gogoproto", + "proto", + "protoc-gen-gogo/descriptor" + ] + revision = "1adfc126b41513cc696b209667c8656ea7aac67c" + version = "v1.0.0" + +[[projects]] + branch = "master" + name = "github.com/kr/logfmt" + packages = ["."] + revision = "b84e30acd515aadc4b783ad4ff83aff3299bdfe0" + +[[projects]] + name = "github.com/pkg/errors" + packages = ["."] + revision = "645ef00459ed84a119197bfb8d8205042c6df63d" + version = "v0.8.0" + +[[projects]] + name = "github.com/pmezard/go-difflib" + packages = ["difflib"] + revision = "792786c7400a136282c1664665ae0a8db921c6c2" + version = "v1.0.0" + +[[projects]] + name = "github.com/stretchr/testify" + packages = [ + "assert", + "require" + ] + revision = "f35b8ab0b5a2cef36673838d662e249dd9c94686" + version = "v1.2.2" + +[[projects]] + branch = "master" + name = "github.com/tendermint/ed25519" + packages = [ + ".", + "edwards25519", + "extra25519" + ] + revision = "d8387025d2b9d158cf4efb07e7ebf814bcce2057" + +[[projects]] + name = "github.com/tendermint/go-amino" + packages = ["."] + revision = "2106ca61d91029c931fd54968c2bb02dc96b1412" + version = "0.10.1" + +[[projects]] + name = "github.com/tendermint/tmlibs" + packages = [ + "common", + "log", + "test" + ] + revision = "692f1d86a6e2c0efa698fd1e4541b68c74ffaf38" + version = "v0.8.4" + +[[projects]] + branch = "master" + name = "golang.org/x/crypto" + packages = [ + "bcrypt", + "blowfish", + "chacha20poly1305", + "hkdf", + "internal/chacha20", + "internal/subtle", + "nacl/secretbox", + "openpgp/armor", + "openpgp/errors", + "poly1305", + "ripemd160", + "salsa20/salsa" + ] + revision = "7f39a6fea4fe9364fb61e1def6a268a51b4f3a06" + +[[projects]] + branch = "master" + name = "golang.org/x/sys" + packages = ["cpu"] + revision = "ad87a3a340fa7f3bed189293fbfa7a9b7e021ae1" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "027b22b86396a971d5d5c1d298947f531f39743975d65a22e98601140aa1b1a1" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/crypto/Gopkg.toml b/crypto/Gopkg.toml new file mode 100644 index 000000000..a614df866 --- /dev/null +++ b/crypto/Gopkg.toml @@ -0,0 +1,49 @@ +# 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" +# +# [prune] +# non-go = false +# go-tests = true +# unused-packages = true + +[[constraint]] + name = "github.com/btcsuite/btcutil" + branch = "master" + +[[constraint]] + name = "github.com/stretchr/testify" + version = "1.2.1" + +[[constraint]] + name = "github.com/tendermint/ed25519" + branch = "master" + +[[constraint]] + name = "github.com/tendermint/go-amino" + version = "0.10.0-rc2" + +[[constraint]] + name = "github.com/tendermint/tmlibs" + version = "0.8.1" + +[prune] + go-tests = true + unused-packages = true diff --git a/crypto/LICENSE b/crypto/LICENSE new file mode 100644 index 000000000..3beb77b13 --- /dev/null +++ b/crypto/LICENSE @@ -0,0 +1,193 @@ +Tendermint Go-Crypto +Copyright (C) 2015 Tendermint + + + + Apache License + Version 2.0, January 2004 + https://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 + + 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 + + https://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/crypto/Makefile b/crypto/Makefile new file mode 100644 index 000000000..a4fd3c37f --- /dev/null +++ b/crypto/Makefile @@ -0,0 +1,99 @@ +GOTOOLS = \ + github.com/golang/dep/cmd/dep \ + # gopkg.in/alecthomas/gometalinter.v2 \ + +GOTOOLS_CHECK = dep #gometalinter.v2 + +all: check get_vendor_deps build test install + +check: check_tools + + +######################################## +### Build + +# Command to generate the workd list (kept here for documentation purposes only): +wordlist: + # To re-generate wordlist.go run: + # go-bindata -ignore ".*\.go" -o keys/words/bip39/wordlist.go -pkg "wordlist" keys/bip39/wordlist/... + +build: wordlist + # Nothing else to build! + +install: + # Nothing to install! + + +######################################## +### Tools & dependencies + +check_tools: + @# https://stackoverflow.com/a/25668869 + @echo "Found tools: $(foreach tool,$(GOTOOLS_CHECK),\ + $(if $(shell which $(tool)),$(tool),$(error "No $(tool) in PATH")))" + +get_tools: + @echo "--> Installing tools" + go get -u -v $(GOTOOLS) + #@gometalinter.v2 --install + +update_tools: + @echo "--> Updating tools" + @go get -u $(GOTOOLS) + +get_vendor_deps: + @rm -rf vendor/ + @echo "--> Running dep ensure" + @dep ensure + + +######################################## +### Testing + +test: + CGO_ENABLED=0 go test -p 1 $(shell go list ./... | grep -v vendor) + +######################################## +### Formatting, linting, and vetting + +fmt: + @go fmt ./... + +metalinter: + @echo "==> Running linter" + gometalinter.v2 --vendor --deadline=600s --disable-all \ + --enable=maligned \ + --enable=deadcode \ + --enable=goconst \ + --enable=goimports \ + --enable=gosimple \ + --enable=ineffassign \ + --enable=megacheck \ + --enable=misspell \ + --enable=staticcheck \ + --enable=safesql \ + --enable=structcheck \ + --enable=unconvert \ + --enable=unused \ + --enable=varcheck \ + --enable=vetshadow \ + ./... + #--enable=gas \ + #--enable=dupl \ + #--enable=errcheck \ + #--enable=gocyclo \ + #--enable=golint \ <== comments on anything exported + #--enable=gotype \ + #--enable=interfacer \ + #--enable=unparam \ + #--enable=vet \ + +metalinter_all: + protoc $(INCLUDE) --lint_out=. types/*.proto + gometalinter.v2 --vendor --deadline=600s --enable-all --disable=lll ./... + + +# To avoid unintended conflicts with file names, always add to .PHONY +# unless there is a reason not to. +# https://www.gnu.org/software/make/manual/html_node/Phony-Targets.html +.PHONEY: check build install check_tools get_tools update_tools get_vendor_deps test fmt metalinter metalinter_all diff --git a/crypto/README.md b/crypto/README.md new file mode 100644 index 000000000..b160f715c --- /dev/null +++ b/crypto/README.md @@ -0,0 +1,25 @@ +# go-crypto + +go-crypto is the cryptographic package adapted for Tendermint's uses + +## Importing it +`import "github.com/tendermint/tendermint/crypto"` + +## Binary encoding + +For Binary encoding, please refer to the [Tendermint encoding spec](https://github.com/tendermint/tendermint/blob/master/docs/spec/blockchain/encoding.md). + +## JSON Encoding + +go-crypto `.Bytes()` uses Amino:binary encoding, but Amino:JSON is also supported. + +```go +Example Amino:JSON encodings: + +crypto.PrivKeyEd25519 - {"type":"954568A3288910","value":"EVkqJO/jIXp3rkASXfh9YnyToYXRXhBr6g9cQVxPFnQBP/5povV4HTjvsy530kybxKHwEi85iU8YL0qQhSYVoQ=="} +crypto.SignatureEd25519 - {"type":"6BF5903DA1DB28","value":"77sQNZOrf7ltExpf7AV1WaYPCHbyRLgjBsoWVzcduuLk+jIGmYk+s5R6Emm29p12HeiNAuhUJgdFGmwkpeGJCA=="} +crypto.PubKeyEd25519 - {"type":"AC26791624DE60","value":"AT/+aaL1eB0477Mud9JMm8Sh8BIvOYlPGC9KkIUmFaE="} +crypto.PrivKeySecp256k1 - {"type":"019E82E1B0F798","value":"zx4Pnh67N+g2V+5vZbQzEyRerX9c4ccNZOVzM9RvJ0Y="} +crypto.SignatureSecp256k1 - {"type":"6D1EA416E1FEE8","value":"MEUCIQCIg5TqS1l7I+MKTrSPIuUN2+4m5tA29dcauqn3NhEJ2wIgICaZ+lgRc5aOTVahU/XoLopXKn8BZcl0bnuYWLvohR8="} +crypto.PubKeySecp256k1 - {"type":"F8CCEAEB5AE980","value":"A8lPKJXcNl5VHt1FK8a244K9EJuS4WX1hFBnwisi0IJx"} +``` diff --git a/crypto/amino.go b/crypto/amino.go new file mode 100644 index 000000000..2a57afdee --- /dev/null +++ b/crypto/amino.go @@ -0,0 +1,37 @@ +package crypto + +import ( + amino "github.com/tendermint/go-amino" +) + +var cdc = amino.NewCodec() + +func init() { + // NOTE: It's important that there be no conflicts here, + // as that would change the canonical representations, + // and therefore change the address. + // TODO: Add feature to go-amino to ensure that there + // are no conflicts. + RegisterAmino(cdc) +} + +// RegisterAmino registers all go-crypto related types in the given (amino) codec. +func RegisterAmino(cdc *amino.Codec) { + cdc.RegisterInterface((*PubKey)(nil), nil) + cdc.RegisterConcrete(PubKeyEd25519{}, + "tendermint/PubKeyEd25519", nil) + cdc.RegisterConcrete(PubKeySecp256k1{}, + "tendermint/PubKeySecp256k1", nil) + + cdc.RegisterInterface((*PrivKey)(nil), nil) + cdc.RegisterConcrete(PrivKeyEd25519{}, + "tendermint/PrivKeyEd25519", nil) + cdc.RegisterConcrete(PrivKeySecp256k1{}, + "tendermint/PrivKeySecp256k1", nil) + + cdc.RegisterInterface((*Signature)(nil), nil) + cdc.RegisterConcrete(SignatureEd25519{}, + "tendermint/SignatureEd25519", nil) + cdc.RegisterConcrete(SignatureSecp256k1{}, + "tendermint/SignatureSecp256k1", nil) +} diff --git a/crypto/armor.go b/crypto/armor.go new file mode 100644 index 000000000..4146048ad --- /dev/null +++ b/crypto/armor.go @@ -0,0 +1,39 @@ +package crypto + +import ( + "bytes" + "fmt" + "io/ioutil" + + "golang.org/x/crypto/openpgp/armor" +) + +func EncodeArmor(blockType string, headers map[string]string, data []byte) string { + buf := new(bytes.Buffer) + w, err := armor.Encode(buf, blockType, headers) + if err != nil { + panic(fmt.Errorf("could not encode ascii armor: %s", err)) + } + _, err = w.Write(data) + if err != nil { + panic(fmt.Errorf("could not encode ascii armor: %s", err)) + } + err = w.Close() + if err != nil { + panic(fmt.Errorf("could not encode ascii armor: %s", err)) + } + return buf.String() +} + +func DecodeArmor(armorStr string) (blockType string, headers map[string]string, data []byte, err error) { + buf := bytes.NewBufferString(armorStr) + block, err := armor.Decode(buf) + if err != nil { + return "", nil, nil, err + } + data, err = ioutil.ReadAll(block.Body) + if err != nil { + return "", nil, nil, err + } + return block.Type, block.Header, data, nil +} diff --git a/crypto/armor_test.go b/crypto/armor_test.go new file mode 100644 index 000000000..5eae87c00 --- /dev/null +++ b/crypto/armor_test.go @@ -0,0 +1,20 @@ +package crypto + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestSimpleArmor(t *testing.T) { + blockType := "MINT TEST" + data := []byte("somedata") + armorStr := EncodeArmor(blockType, nil, data) + + // Decode armorStr and test for equivalence. + blockType2, _, data2, err := DecodeArmor(armorStr) + require.Nil(t, err, "%+v", err) + assert.Equal(t, blockType, blockType2) + assert.Equal(t, data, data2) +} diff --git a/crypto/doc.go b/crypto/doc.go new file mode 100644 index 000000000..c6701bc58 --- /dev/null +++ b/crypto/doc.go @@ -0,0 +1,48 @@ +/* +go-crypto is a customized/convenience cryptography package +for supporting Tendermint. + +It wraps select functionality of equivalent functions in the +Go standard library, for easy usage with our libraries. + +Keys: + +All key generation functions return an instance of the PrivKey interface +which implements methods + + AssertIsPrivKeyInner() + Bytes() []byte + Sign(msg []byte) Signature + PubKey() PubKey + Equals(PrivKey) bool + Wrap() PrivKey + +From the above method we can: +a) Retrieve the public key if needed + + pubKey := key.PubKey() + +For example: + privKey, err := crypto.GenPrivKeyEd25519() + if err != nil { + ... + } + pubKey := privKey.PubKey() + ... + // And then you can use the private and public key + doSomething(privKey, pubKey) + + +We also provide hashing wrappers around algorithms: + +Sha256 + sum := crypto.Sha256([]byte("This is Tendermint")) + fmt.Printf("%x\n", sum) + +Ripemd160 + sum := crypto.Ripemd160([]byte("This is consensus")) + fmt.Printf("%x\n", sum) +*/ +package crypto + +// TODO: Add more docs in here diff --git a/crypto/encode_test.go b/crypto/encode_test.go new file mode 100644 index 000000000..16555bf71 --- /dev/null +++ b/crypto/encode_test.go @@ -0,0 +1,119 @@ +package crypto + +import ( + "os" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +type byter interface { + Bytes() []byte +} + +func checkAminoBinary(t *testing.T, src byter, dst interface{}, size int) { + // Marshal to binary bytes. + bz, err := cdc.MarshalBinaryBare(src) + require.Nil(t, err, "%+v", err) + // Make sure this is compatible with current (Bytes()) encoding. + assert.Equal(t, src.Bytes(), bz, "Amino binary vs Bytes() mismatch") + // Make sure we have the expected length. + if size != -1 { + assert.Equal(t, size, len(bz), "Amino binary size mismatch") + } + // Unmarshal. + err = cdc.UnmarshalBinaryBare(bz, dst) + require.Nil(t, err, "%+v", err) +} + +func checkAminoJSON(t *testing.T, src interface{}, dst interface{}, isNil bool) { + // Marshal to JSON bytes. + js, err := cdc.MarshalJSON(src) + require.Nil(t, err, "%+v", err) + if isNil { + assert.Equal(t, string(js), `null`) + } else { + assert.Contains(t, string(js), `"type":`) + assert.Contains(t, string(js), `"value":`) + } + // Unmarshal. + err = cdc.UnmarshalJSON(js, dst) + require.Nil(t, err, "%+v", err) +} + +func ExamplePrintRegisteredTypes() { + cdc.PrintTypes(os.Stdout) + // Output: | Type | Name | Prefix | Length | Notes | + //| ---- | ---- | ------ | ----- | ------ | + //| PubKeyEd25519 | tendermint/PubKeyEd25519 | 0x1624DE64 | 0x20 | | + //| PubKeySecp256k1 | tendermint/PubKeySecp256k1 | 0xEB5AE987 | 0x21 | | + //| PrivKeyEd25519 | tendermint/PrivKeyEd25519 | 0xA3288910 | 0x40 | | + //| PrivKeySecp256k1 | tendermint/PrivKeySecp256k1 | 0xE1B0F79B | 0x20 | | + //| SignatureEd25519 | tendermint/SignatureEd25519 | 0x2031EA53 | 0x40 | | + //| SignatureSecp256k1 | tendermint/SignatureSecp256k1 | 0x7FC4A495 | variable | | +} + +func TestKeyEncodings(t *testing.T) { + cases := []struct { + privKey PrivKey + privSize, pubSize int // binary sizes + }{ + { + privKey: GenPrivKeyEd25519(), + privSize: 69, + pubSize: 37, + }, + { + privKey: GenPrivKeySecp256k1(), + privSize: 37, + pubSize: 38, + }, + } + + for _, tc := range cases { + + // Check (de/en)codings of PrivKeys. + var priv2, priv3 PrivKey + checkAminoBinary(t, tc.privKey, &priv2, tc.privSize) + assert.EqualValues(t, tc.privKey, priv2) + checkAminoJSON(t, tc.privKey, &priv3, false) // TODO also check Prefix bytes. + assert.EqualValues(t, tc.privKey, priv3) + + // Check (de/en)codings of Signatures. + var sig1, sig2, sig3 Signature + sig1, err := tc.privKey.Sign([]byte("something")) + assert.NoError(t, err) + checkAminoBinary(t, sig1, &sig2, -1) // Signature size changes for Secp anyways. + assert.EqualValues(t, sig1, sig2) + checkAminoJSON(t, sig1, &sig3, false) // TODO also check Prefix bytes. + assert.EqualValues(t, sig1, sig3) + + // Check (de/en)codings of PubKeys. + pubKey := tc.privKey.PubKey() + var pub2, pub3 PubKey + checkAminoBinary(t, pubKey, &pub2, tc.pubSize) + assert.EqualValues(t, pubKey, pub2) + checkAminoJSON(t, pubKey, &pub3, false) // TODO also check Prefix bytes. + assert.EqualValues(t, pubKey, pub3) + } +} + +func TestNilEncodings(t *testing.T) { + + // Check nil Signature. + var a, b Signature + checkAminoJSON(t, &a, &b, true) + assert.EqualValues(t, a, b) + + // Check nil PubKey. + var c, d PubKey + checkAminoJSON(t, &c, &d, true) + assert.EqualValues(t, c, d) + + // Check nil PrivKey. + var e, f PrivKey + checkAminoJSON(t, &e, &f, true) + assert.EqualValues(t, e, f) + +} diff --git a/crypto/example_test.go b/crypto/example_test.go new file mode 100644 index 000000000..904e1c610 --- /dev/null +++ b/crypto/example_test.go @@ -0,0 +1,35 @@ +// Copyright 2017 Tendermint. 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 crypto_test + +import ( + "fmt" + + "github.com/tendermint/tendermint/crypto" +) + +func ExampleSha256() { + sum := crypto.Sha256([]byte("This is Tendermint")) + fmt.Printf("%x\n", sum) + // Output: + // f91afb642f3d1c87c17eb01aae5cb65c242dfdbe7cf1066cc260f4ce5d33b94e +} + +func ExampleRipemd160() { + sum := crypto.Ripemd160([]byte("This is Tendermint")) + fmt.Printf("%x\n", sum) + // Output: + // 051e22663e8f0fd2f2302f1210f954adff009005 +} diff --git a/crypto/hash.go b/crypto/hash.go new file mode 100644 index 000000000..165b1e153 --- /dev/null +++ b/crypto/hash.go @@ -0,0 +1,18 @@ +package crypto + +import ( + "crypto/sha256" + "golang.org/x/crypto/ripemd160" +) + +func Sha256(bytes []byte) []byte { + hasher := sha256.New() + hasher.Write(bytes) + return hasher.Sum(nil) +} + +func Ripemd160(bytes []byte) []byte { + hasher := ripemd160.New() + hasher.Write(bytes) + return hasher.Sum(nil) +} diff --git a/crypto/hkdfchacha20poly1305/hkdfchachapoly.go b/crypto/hkdfchacha20poly1305/hkdfchachapoly.go new file mode 100644 index 000000000..ab3b9df3a --- /dev/null +++ b/crypto/hkdfchacha20poly1305/hkdfchachapoly.go @@ -0,0 +1,105 @@ +// Package hkdfchacha20poly1305 creates an AEAD using hkdf, chacha20, and poly1305 +// When sealing and opening, the hkdf is used to obtain the nonce and subkey for +// chacha20. Other than the change for the how the subkey and nonce for chacha +// are obtained, this is the same as chacha20poly1305 +package hkdfchacha20poly1305 + +import ( + "crypto/cipher" + "crypto/sha256" + "errors" + "io" + + "golang.org/x/crypto/chacha20poly1305" + "golang.org/x/crypto/hkdf" +) + +type hkdfchacha20poly1305 struct { + key [KeySize]byte +} + +const ( + // KeySize is the size of the key used by this AEAD, in bytes. + KeySize = 32 + // NonceSize is the size of the nonce used with this AEAD, in bytes. + NonceSize = 24 + // TagSize is the size added from poly1305 + TagSize = 16 + // MaxPlaintextSize is the max size that can be passed into a single call of Seal + MaxPlaintextSize = (1 << 38) - 64 + // MaxCiphertextSize is the max size that can be passed into a single call of Open, + // this differs from plaintext size due to the tag + MaxCiphertextSize = (1 << 38) - 48 + // HkdfInfo is the parameter used internally for Hkdf's info parameter. + HkdfInfo = "TENDERMINT_SECRET_CONNECTION_FRAME_KEY_DERIVE" +) + +//New xChaChapoly1305 AEAD with 24 byte nonces +func New(key []byte) (cipher.AEAD, error) { + if len(key) != KeySize { + return nil, errors.New("chacha20poly1305: bad key length") + } + ret := new(hkdfchacha20poly1305) + copy(ret.key[:], key) + return ret, nil + +} +func (c *hkdfchacha20poly1305) NonceSize() int { + return NonceSize +} + +func (c *hkdfchacha20poly1305) Overhead() int { + return TagSize +} + +func (c *hkdfchacha20poly1305) Seal(dst, nonce, plaintext, additionalData []byte) []byte { + if len(nonce) != NonceSize { + panic("hkdfchacha20poly1305: bad nonce length passed to Seal") + } + + if uint64(len(plaintext)) > MaxPlaintextSize { + panic("hkdfchacha20poly1305: plaintext too large") + } + + subKey, chachaNonce := getSubkeyAndChachaNonceFromHkdf(&c.key, &nonce) + + aead, err := chacha20poly1305.New(subKey[:]) + if err != nil { + panic("hkdfchacha20poly1305: failed to initialize chacha20poly1305") + } + + return aead.Seal(dst, chachaNonce[:], plaintext, additionalData) +} + +func (c *hkdfchacha20poly1305) Open(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) { + if len(nonce) != NonceSize { + return nil, errors.New("hkdfchacha20poly1305: bad nonce length passed to Open") + } + if uint64(len(ciphertext)) > MaxCiphertextSize { + return nil, errors.New("hkdfchacha20poly1305: ciphertext too large") + } + + subKey, chachaNonce := getSubkeyAndChachaNonceFromHkdf(&c.key, &nonce) + + aead, err := chacha20poly1305.New(subKey[:]) + if err != nil { + panic("hkdfchacha20poly1305: failed to initialize chacha20poly1305") + } + + return aead.Open(dst, chachaNonce[:], ciphertext, additionalData) +} + +func getSubkeyAndChachaNonceFromHkdf(cKey *[32]byte, nonce *[]byte) ( + subKey [KeySize]byte, chachaNonce [chacha20poly1305.NonceSize]byte) { + hash := sha256.New + hkdf := hkdf.New(hash, (*cKey)[:], *nonce, []byte(HkdfInfo)) + _, err := io.ReadFull(hkdf, subKey[:]) + if err != nil { + panic("hkdfchacha20poly1305: failed to read subkey from hkdf") + } + _, err = io.ReadFull(hkdf, chachaNonce[:]) + if err != nil { + panic("hkdfchacha20poly1305: failed to read chachaNonce from hkdf") + } + return +} diff --git a/crypto/hkdfchacha20poly1305/hkdfchachapoly_test.go b/crypto/hkdfchacha20poly1305/hkdfchachapoly_test.go new file mode 100644 index 000000000..fb9c4afcd --- /dev/null +++ b/crypto/hkdfchacha20poly1305/hkdfchachapoly_test.go @@ -0,0 +1,139 @@ +package hkdfchacha20poly1305 + +import ( + "bytes" + cr "crypto/rand" + "encoding/hex" + mr "math/rand" + "testing" + + "github.com/stretchr/testify/assert" +) + +// Test that a test vector we generated is valid. (Ensures backwards +// compatibility) +func TestVector(t *testing.T) { + key, _ := hex.DecodeString("56f8de45d3c294c7675bcaf457bdd4b71c380b9b2408ce9412b348d0f08b69ee") + aead, err := New(key[:]) + if err != nil { + t.Fatal(err) + } + cts := []string{"e20a8bf42c535ac30125cfc52031577f0b", + "657695b37ba30f67b25860d90a6f1d00d8", + "e9aa6f3b7f625d957fd50f05bcdf20d014", + "8a00b3b5a6014e0d2033bebc5935086245", + "aadd74867b923879e6866ea9e03c009039", + "fc59773c2c864ee3b4cc971876b3c7bed4", + "caec14e3a9a52ce1a2682c6737defa4752", + "0b89511ffe490d2049d6950494ee51f919", + "7de854ea71f43ca35167a07566c769083d", + "cd477327f4ea4765c71e311c5fec1edbfb"} + + for i := 0; i < 10; i++ { + ct, _ := hex.DecodeString(cts[i]) + + byteArr := []byte{byte(i)} + nonce := make([]byte, 24) + nonce[0] = byteArr[0] + + plaintext, err := aead.Open(nil, nonce, ct, byteArr) + if err != nil { + t.Errorf("%dth Open failed", i) + continue + } + assert.Equal(t, byteArr, plaintext) + } +} + +// The following test is taken from +// https://github.com/golang/crypto/blob/master/chacha20poly1305/chacha20poly1305_test.go#L69 +// It requires the below copyright notice, where "this source code" refers to the following function. +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found at the bottom of this file. +func TestRandom(t *testing.T) { + // Some random tests to verify Open(Seal) == Plaintext + for i := 0; i < 256; i++ { + var nonce [24]byte + var key [32]byte + + al := mr.Intn(128) + pl := mr.Intn(16384) + ad := make([]byte, al) + plaintext := make([]byte, pl) + cr.Read(key[:]) + cr.Read(nonce[:]) + cr.Read(ad) + cr.Read(plaintext) + + aead, err := New(key[:]) + if err != nil { + t.Fatal(err) + } + + ct := aead.Seal(nil, nonce[:], plaintext, ad) + + plaintext2, err := aead.Open(nil, nonce[:], ct, ad) + if err != nil { + t.Errorf("Random #%d: Open failed", i) + continue + } + + if !bytes.Equal(plaintext, plaintext2) { + t.Errorf("Random #%d: plaintext's don't match: got %x vs %x", i, plaintext2, plaintext) + continue + } + + if len(ad) > 0 { + alterAdIdx := mr.Intn(len(ad)) + ad[alterAdIdx] ^= 0x80 + if _, err := aead.Open(nil, nonce[:], ct, ad); err == nil { + t.Errorf("Random #%d: Open was successful after altering additional data", i) + } + ad[alterAdIdx] ^= 0x80 + } + + alterNonceIdx := mr.Intn(aead.NonceSize()) + nonce[alterNonceIdx] ^= 0x80 + if _, err := aead.Open(nil, nonce[:], ct, ad); err == nil { + t.Errorf("Random #%d: Open was successful after altering nonce", i) + } + nonce[alterNonceIdx] ^= 0x80 + + alterCtIdx := mr.Intn(len(ct)) + ct[alterCtIdx] ^= 0x80 + if _, err := aead.Open(nil, nonce[:], ct, ad); err == nil { + t.Errorf("Random #%d: Open was successful after altering ciphertext", i) + } + ct[alterCtIdx] ^= 0x80 + } +} + +// AFOREMENTIONED LICENCE +// Copyright (c) 2009 The Go Authors. 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 Google Inc. 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 +// 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. diff --git a/crypto/merkle/README.md b/crypto/merkle/README.md new file mode 100644 index 000000000..c44978368 --- /dev/null +++ b/crypto/merkle/README.md @@ -0,0 +1,4 @@ +## Simple Merkle Tree + +For smaller static data structures that don't require immutable snapshots or mutability; +for instance the transactions and validation signatures of a block can be hashed using this simple merkle tree logic. diff --git a/crypto/merkle/doc.go b/crypto/merkle/doc.go new file mode 100644 index 000000000..da65dd858 --- /dev/null +++ b/crypto/merkle/doc.go @@ -0,0 +1,31 @@ +/* +Package merkle computes a deterministic minimal height Merkle tree hash. +If the number of items is not a power of two, some leaves +will be at different levels. Tries to keep both sides of +the tree the same size, but the left may be one greater. + +Use this for short deterministic trees, such as the validator list. +For larger datasets, use IAVLTree. + +Be aware that the current implementation by itself does not prevent +second pre-image attacks. Hence, use this library with caution. +Otherwise you might run into similar issues as, e.g., in early Bitcoin: +https://bitcointalk.org/?topic=102395 + + * + / \ + / \ + / \ + / \ + * * + / \ / \ + / \ / \ + / \ / \ + * * * h6 + / \ / \ / \ + h0 h1 h2 h3 h4 h5 + +TODO(ismail): add 2nd pre-image protection or clarify further on how we use this and why this secure. + +*/ +package merkle \ No newline at end of file diff --git a/crypto/merkle/simple_map.go b/crypto/merkle/simple_map.go new file mode 100644 index 000000000..86a9bad9c --- /dev/null +++ b/crypto/merkle/simple_map.go @@ -0,0 +1,88 @@ +package merkle + +import ( + "github.com/tendermint/tendermint/crypto/tmhash" + cmn "github.com/tendermint/tmlibs/common" +) + +// Merkle tree from a map. +// Leaves are `hash(key) | hash(value)`. +// Leaves are sorted before Merkle hashing. +type simpleMap struct { + kvs cmn.KVPairs + sorted bool +} + +func newSimpleMap() *simpleMap { + return &simpleMap{ + kvs: nil, + sorted: false, + } +} + +// Set hashes the key and value and appends it to the kv pairs. +func (sm *simpleMap) Set(key string, value Hasher) { + sm.sorted = false + + // The value is hashed, so you can + // check for equality with a cached value (say) + // and make a determination to fetch or not. + vhash := value.Hash() + + sm.kvs = append(sm.kvs, cmn.KVPair{ + Key: []byte(key), + Value: vhash, + }) +} + +// Hash Merkle root hash of items sorted by key +// (UNSTABLE: and by value too if duplicate key). +func (sm *simpleMap) Hash() []byte { + sm.Sort() + return hashKVPairs(sm.kvs) +} + +func (sm *simpleMap) Sort() { + if sm.sorted { + return + } + sm.kvs.Sort() + sm.sorted = true +} + +// Returns a copy of sorted KVPairs. +// NOTE these contain the hashed key and value. +func (sm *simpleMap) KVPairs() cmn.KVPairs { + sm.Sort() + kvs := make(cmn.KVPairs, len(sm.kvs)) + copy(kvs, sm.kvs) + return kvs +} + +//---------------------------------------- + +// A local extension to KVPair that can be hashed. +// Key and value are length prefixed and concatenated, +// then hashed. +type KVPair cmn.KVPair + +func (kv KVPair) Hash() []byte { + hasher := tmhash.New() + err := encodeByteSlice(hasher, kv.Key) + if err != nil { + panic(err) + } + err = encodeByteSlice(hasher, kv.Value) + if err != nil { + panic(err) + } + return hasher.Sum(nil) +} + +func hashKVPairs(kvs cmn.KVPairs) []byte { + kvsH := make([]Hasher, len(kvs)) + for i, kvp := range kvs { + kvsH[i] = KVPair(kvp) + } + return SimpleHashFromHashers(kvsH) +} diff --git a/crypto/merkle/simple_map_test.go b/crypto/merkle/simple_map_test.go new file mode 100644 index 000000000..34febcf16 --- /dev/null +++ b/crypto/merkle/simple_map_test.go @@ -0,0 +1,54 @@ +package merkle + +import ( + "fmt" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/tendermint/tendermint/crypto/tmhash" +) + +type strHasher string + +func (str strHasher) Hash() []byte { + return tmhash.Sum([]byte(str)) +} + +func TestSimpleMap(t *testing.T) { + { + db := newSimpleMap() + db.Set("key1", strHasher("value1")) + assert.Equal(t, "fa9bc106ffd932d919bee935ceb6cf2b3dd72d8f", fmt.Sprintf("%x", db.Hash()), "Hash didn't match") + } + { + db := newSimpleMap() + db.Set("key1", strHasher("value2")) + assert.Equal(t, "e00e7dcfe54e9fafef5111e813a587f01ba9c3e8", fmt.Sprintf("%x", db.Hash()), "Hash didn't match") + } + { + db := newSimpleMap() + db.Set("key1", strHasher("value1")) + db.Set("key2", strHasher("value2")) + assert.Equal(t, "eff12d1c703a1022ab509287c0f196130123d786", fmt.Sprintf("%x", db.Hash()), "Hash didn't match") + } + { + db := newSimpleMap() + db.Set("key2", strHasher("value2")) // NOTE: out of order + db.Set("key1", strHasher("value1")) + assert.Equal(t, "eff12d1c703a1022ab509287c0f196130123d786", fmt.Sprintf("%x", db.Hash()), "Hash didn't match") + } + { + db := newSimpleMap() + db.Set("key1", strHasher("value1")) + db.Set("key2", strHasher("value2")) + db.Set("key3", strHasher("value3")) + assert.Equal(t, "b2c62a277c08dbd2ad73ca53cd1d6bfdf5830d26", fmt.Sprintf("%x", db.Hash()), "Hash didn't match") + } + { + db := newSimpleMap() + db.Set("key2", strHasher("value2")) // NOTE: out of order + db.Set("key1", strHasher("value1")) + db.Set("key3", strHasher("value3")) + assert.Equal(t, "b2c62a277c08dbd2ad73ca53cd1d6bfdf5830d26", fmt.Sprintf("%x", db.Hash()), "Hash didn't match") + } +} diff --git a/crypto/merkle/simple_proof.go b/crypto/merkle/simple_proof.go new file mode 100644 index 000000000..2541b6d38 --- /dev/null +++ b/crypto/merkle/simple_proof.go @@ -0,0 +1,160 @@ +package merkle + +import ( + "bytes" + "fmt" +) + +// SimpleProof represents a simple merkle proof. +type SimpleProof struct { + Aunts [][]byte `json:"aunts"` // Hashes from leaf's sibling to a root's child. +} + +// SimpleProofsFromHashers computes inclusion proof for given items. +// proofs[0] is the proof for items[0]. +func SimpleProofsFromHashers(items []Hasher) (rootHash []byte, proofs []*SimpleProof) { + trails, rootSPN := trailsFromHashers(items) + rootHash = rootSPN.Hash + proofs = make([]*SimpleProof, len(items)) + for i, trail := range trails { + proofs[i] = &SimpleProof{ + Aunts: trail.FlattenAunts(), + } + } + return +} + +// SimpleProofsFromMap generates proofs from a map. The keys/values of the map will be used as the keys/values +// in the underlying key-value pairs. +// The keys are sorted before the proofs are computed. +func SimpleProofsFromMap(m map[string]Hasher) (rootHash []byte, proofs map[string]*SimpleProof, keys []string) { + sm := newSimpleMap() + for k, v := range m { + sm.Set(k, v) + } + sm.Sort() + kvs := sm.kvs + kvsH := make([]Hasher, 0, len(kvs)) + for _, kvp := range kvs { + kvsH = append(kvsH, KVPair(kvp)) + } + + rootHash, proofList := SimpleProofsFromHashers(kvsH) + proofs = make(map[string]*SimpleProof) + keys = make([]string, len(proofList)) + for i, kvp := range kvs { + proofs[string(kvp.Key)] = proofList[i] + keys[i] = string(kvp.Key) + } + return +} + +// Verify that leafHash is a leaf hash of the simple-merkle-tree +// which hashes to rootHash. +func (sp *SimpleProof) Verify(index int, total int, leafHash []byte, rootHash []byte) bool { + computedHash := computeHashFromAunts(index, total, leafHash, sp.Aunts) + return computedHash != nil && bytes.Equal(computedHash, rootHash) +} + +// String implements the stringer interface for SimpleProof. +// It is a wrapper around StringIndented. +func (sp *SimpleProof) String() string { + return sp.StringIndented("") +} + +// StringIndented generates a canonical string representation of a SimpleProof. +func (sp *SimpleProof) StringIndented(indent string) string { + return fmt.Sprintf(`SimpleProof{ +%s Aunts: %X +%s}`, + indent, sp.Aunts, + indent) +} + +// Use the leafHash and innerHashes to get the root merkle hash. +// If the length of the innerHashes slice isn't exactly correct, the result is nil. +// Recursive impl. +func computeHashFromAunts(index int, total int, leafHash []byte, innerHashes [][]byte) []byte { + if index >= total || index < 0 || total <= 0 { + return nil + } + switch total { + case 0: + panic("Cannot call computeHashFromAunts() with 0 total") + case 1: + if len(innerHashes) != 0 { + return nil + } + return leafHash + default: + if len(innerHashes) == 0 { + return nil + } + numLeft := (total + 1) / 2 + if index < numLeft { + leftHash := computeHashFromAunts(index, numLeft, leafHash, innerHashes[:len(innerHashes)-1]) + if leftHash == nil { + return nil + } + return SimpleHashFromTwoHashes(leftHash, innerHashes[len(innerHashes)-1]) + } + rightHash := computeHashFromAunts(index-numLeft, total-numLeft, leafHash, innerHashes[:len(innerHashes)-1]) + if rightHash == nil { + return nil + } + return SimpleHashFromTwoHashes(innerHashes[len(innerHashes)-1], rightHash) + } +} + +// SimpleProofNode is a helper structure to construct merkle proof. +// The node and the tree is thrown away afterwards. +// Exactly one of node.Left and node.Right is nil, unless node is the root, in which case both are nil. +// node.Parent.Hash = hash(node.Hash, node.Right.Hash) or +// hash(node.Left.Hash, node.Hash), depending on whether node is a left/right child. +type SimpleProofNode struct { + Hash []byte + Parent *SimpleProofNode + Left *SimpleProofNode // Left sibling (only one of Left,Right is set) + Right *SimpleProofNode // Right sibling (only one of Left,Right is set) +} + +// FlattenAunts will return the inner hashes for the item corresponding to the leaf, +// starting from a leaf SimpleProofNode. +func (spn *SimpleProofNode) FlattenAunts() [][]byte { + // Nonrecursive impl. + innerHashes := [][]byte{} + for spn != nil { + if spn.Left != nil { + innerHashes = append(innerHashes, spn.Left.Hash) + } else if spn.Right != nil { + innerHashes = append(innerHashes, spn.Right.Hash) + } else { + break + } + spn = spn.Parent + } + return innerHashes +} + +// trails[0].Hash is the leaf hash for items[0]. +// trails[i].Parent.Parent....Parent == root for all i. +func trailsFromHashers(items []Hasher) (trails []*SimpleProofNode, root *SimpleProofNode) { + // Recursive impl. + switch len(items) { + case 0: + return nil, nil + case 1: + trail := &SimpleProofNode{items[0].Hash(), nil, nil, nil} + return []*SimpleProofNode{trail}, trail + default: + lefts, leftRoot := trailsFromHashers(items[:(len(items)+1)/2]) + rights, rightRoot := trailsFromHashers(items[(len(items)+1)/2:]) + rootHash := SimpleHashFromTwoHashes(leftRoot.Hash, rightRoot.Hash) + root := &SimpleProofNode{rootHash, nil, nil, nil} + leftRoot.Parent = root + leftRoot.Right = rightRoot + rightRoot.Parent = root + rightRoot.Left = leftRoot + return append(lefts, rights...), root + } +} diff --git a/crypto/merkle/simple_tree.go b/crypto/merkle/simple_tree.go new file mode 100644 index 000000000..35a6eaa7c --- /dev/null +++ b/crypto/merkle/simple_tree.go @@ -0,0 +1,58 @@ +package merkle + +import ( + "github.com/tendermint/tendermint/crypto/tmhash" +) + +// SimpleHashFromTwoHashes is the basic operation of the Merkle tree: Hash(left | right). +func SimpleHashFromTwoHashes(left, right []byte) []byte { + var hasher = tmhash.New() + err := encodeByteSlice(hasher, left) + if err != nil { + panic(err) + } + err = encodeByteSlice(hasher, right) + if err != nil { + panic(err) + } + return hasher.Sum(nil) +} + +// SimpleHashFromHashers computes a Merkle tree from items that can be hashed. +func SimpleHashFromHashers(items []Hasher) []byte { + hashes := make([][]byte, len(items)) + for i, item := range items { + hash := item.Hash() + hashes[i] = hash + } + return simpleHashFromHashes(hashes) +} + +// SimpleHashFromMap computes a Merkle tree from sorted map. +// Like calling SimpleHashFromHashers with +// `item = []byte(Hash(key) | Hash(value))`, +// sorted by `item`. +func SimpleHashFromMap(m map[string]Hasher) []byte { + sm := newSimpleMap() + for k, v := range m { + sm.Set(k, v) + } + return sm.Hash() +} + +//---------------------------------------------------------------- + +// Expects hashes! +func simpleHashFromHashes(hashes [][]byte) []byte { + // Recursive impl. + switch len(hashes) { + case 0: + return nil + case 1: + return hashes[0] + default: + left := simpleHashFromHashes(hashes[:(len(hashes)+1)/2]) + right := simpleHashFromHashes(hashes[(len(hashes)+1)/2:]) + return SimpleHashFromTwoHashes(left, right) + } +} diff --git a/crypto/merkle/simple_tree_test.go b/crypto/merkle/simple_tree_test.go new file mode 100644 index 000000000..a721bccea --- /dev/null +++ b/crypto/merkle/simple_tree_test.go @@ -0,0 +1,88 @@ +package merkle + +import ( + "bytes" + + cmn "github.com/tendermint/tmlibs/common" + . "github.com/tendermint/tmlibs/test" + + "testing" + "github.com/tendermint/tendermint/crypto/tmhash" +) + +type testItem []byte + +func (tI testItem) Hash() []byte { + return []byte(tI) +} + +func TestSimpleProof(t *testing.T) { + + total := 100 + + items := make([]Hasher, total) + for i := 0; i < total; i++ { + items[i] = testItem(cmn.RandBytes(tmhash.Size)) + } + + rootHash := SimpleHashFromHashers(items) + + rootHash2, proofs := SimpleProofsFromHashers(items) + + if !bytes.Equal(rootHash, rootHash2) { + t.Errorf("Unmatched root hashes: %X vs %X", rootHash, rootHash2) + } + + // For each item, check the trail. + for i, item := range items { + itemHash := item.Hash() + proof := proofs[i] + + // Verify success + ok := proof.Verify(i, total, itemHash, rootHash) + if !ok { + t.Errorf("Verification failed for index %v.", i) + } + + // Wrong item index should make it fail + { + ok = proof.Verify((i+1)%total, total, itemHash, rootHash) + if ok { + t.Errorf("Expected verification to fail for wrong index %v.", i) + } + } + + // Trail too long should make it fail + origAunts := proof.Aunts + proof.Aunts = append(proof.Aunts, cmn.RandBytes(32)) + { + ok = proof.Verify(i, total, itemHash, rootHash) + if ok { + t.Errorf("Expected verification to fail for wrong trail length.") + } + } + proof.Aunts = origAunts + + // Trail too short should make it fail + proof.Aunts = proof.Aunts[0 : len(proof.Aunts)-1] + { + ok = proof.Verify(i, total, itemHash, rootHash) + if ok { + t.Errorf("Expected verification to fail for wrong trail length.") + } + } + proof.Aunts = origAunts + + // Mutating the itemHash should make it fail. + ok = proof.Verify(i, total, MutateByteSlice(itemHash), rootHash) + if ok { + t.Errorf("Expected verification to fail for mutated leaf hash") + } + + // Mutating the rootHash should make it fail. + ok = proof.Verify(i, total, itemHash, MutateByteSlice(rootHash)) + if ok { + t.Errorf("Expected verification to fail for mutated root hash") + } + } +} diff --git a/crypto/merkle/types.go b/crypto/merkle/types.go new file mode 100644 index 000000000..2fcb3f39d --- /dev/null +++ b/crypto/merkle/types.go @@ -0,0 +1,38 @@ +package merkle + +import ( + "io" + + amino "github.com/tendermint/go-amino" +) + +// Tree is a Merkle tree interface. +type Tree interface { + Size() (size int) + Height() (height int8) + Has(key []byte) (has bool) + Proof(key []byte) (value []byte, proof []byte, exists bool) // TODO make it return an index + Get(key []byte) (index int, value []byte, exists bool) + GetByIndex(index int) (key []byte, value []byte) + Set(key []byte, value []byte) (updated bool) + Remove(key []byte) (value []byte, removed bool) + HashWithCount() (hash []byte, count int) + Hash() (hash []byte) + Save() (hash []byte) + Load(hash []byte) + Copy() Tree + Iterate(func(key []byte, value []byte) (stop bool)) (stopped bool) + IterateRange(start []byte, end []byte, ascending bool, fx func(key []byte, value []byte) (stop bool)) (stopped bool) +} + +// Hasher represents a hashable piece of data which can be hashed in the Tree. +type Hasher interface { + Hash() []byte +} + +//----------------------------------------------------------------------- + +// Uvarint length prefixed byteslice +func encodeByteSlice(w io.Writer, bz []byte) (err error) { + return amino.EncodeByteSlice(w, bz) +} diff --git a/crypto/priv_key.go b/crypto/priv_key.go new file mode 100644 index 000000000..dbfe64c33 --- /dev/null +++ b/crypto/priv_key.go @@ -0,0 +1,164 @@ +package crypto + +import ( + "crypto/subtle" + + secp256k1 "github.com/btcsuite/btcd/btcec" + "github.com/tendermint/ed25519" + "github.com/tendermint/ed25519/extra25519" +) + +func PrivKeyFromBytes(privKeyBytes []byte) (privKey PrivKey, err error) { + err = cdc.UnmarshalBinaryBare(privKeyBytes, &privKey) + return +} + +//---------------------------------------- + +type PrivKey interface { + Bytes() []byte + Sign(msg []byte) (Signature, error) + PubKey() PubKey + Equals(PrivKey) bool +} + +//------------------------------------- + +var _ PrivKey = PrivKeyEd25519{} + +// Implements PrivKey +type PrivKeyEd25519 [64]byte + +func (privKey PrivKeyEd25519) Bytes() []byte { + return cdc.MustMarshalBinaryBare(privKey) +} + +func (privKey PrivKeyEd25519) Sign(msg []byte) (Signature, error) { + privKeyBytes := [64]byte(privKey) + signatureBytes := ed25519.Sign(&privKeyBytes, msg) + return SignatureEd25519(*signatureBytes), nil +} + +func (privKey PrivKeyEd25519) PubKey() PubKey { + privKeyBytes := [64]byte(privKey) + pubBytes := *ed25519.MakePublicKey(&privKeyBytes) + return PubKeyEd25519(pubBytes) +} + +// Equals - you probably don't need to use this. +// Runs in constant time based on length of the keys. +func (privKey PrivKeyEd25519) Equals(other PrivKey) bool { + if otherEd, ok := other.(PrivKeyEd25519); ok { + return subtle.ConstantTimeCompare(privKey[:], otherEd[:]) == 1 + } else { + return false + } +} + +func (privKey PrivKeyEd25519) ToCurve25519() *[32]byte { + keyCurve25519 := new([32]byte) + privKeyBytes := [64]byte(privKey) + extra25519.PrivateKeyToCurve25519(keyCurve25519, &privKeyBytes) + return keyCurve25519 +} + +// Deterministically generates new priv-key bytes from key. +func (privKey PrivKeyEd25519) Generate(index int) PrivKeyEd25519 { + bz, err := cdc.MarshalBinaryBare(struct { + PrivKey [64]byte + Index int + }{privKey, index}) + if err != nil { + panic(err) + } + newBytes := Sha256(bz) + newKey := new([64]byte) + copy(newKey[:32], newBytes) + ed25519.MakePublicKey(newKey) + return PrivKeyEd25519(*newKey) +} + +func GenPrivKeyEd25519() PrivKeyEd25519 { + privKeyBytes := new([64]byte) + copy(privKeyBytes[:32], CRandBytes(32)) + ed25519.MakePublicKey(privKeyBytes) + return PrivKeyEd25519(*privKeyBytes) +} + +// NOTE: secret should be the output of a KDF like bcrypt, +// if it's derived from user input. +func GenPrivKeyEd25519FromSecret(secret []byte) PrivKeyEd25519 { + privKey32 := Sha256(secret) // Not Ripemd160 because we want 32 bytes. + privKeyBytes := new([64]byte) + copy(privKeyBytes[:32], privKey32) + ed25519.MakePublicKey(privKeyBytes) + return PrivKeyEd25519(*privKeyBytes) +} + +//------------------------------------- + +var _ PrivKey = PrivKeySecp256k1{} + +// Implements PrivKey +type PrivKeySecp256k1 [32]byte + +func (privKey PrivKeySecp256k1) Bytes() []byte { + return cdc.MustMarshalBinaryBare(privKey) +} + +func (privKey PrivKeySecp256k1) Sign(msg []byte) (Signature, error) { + priv__, _ := secp256k1.PrivKeyFromBytes(secp256k1.S256(), privKey[:]) + sig__, err := priv__.Sign(Sha256(msg)) + if err != nil { + return nil, err + } + return SignatureSecp256k1(sig__.Serialize()), nil +} + +func (privKey PrivKeySecp256k1) PubKey() PubKey { + _, pub__ := secp256k1.PrivKeyFromBytes(secp256k1.S256(), privKey[:]) + var pub PubKeySecp256k1 + copy(pub[:], pub__.SerializeCompressed()) + return pub +} + +// Equals - you probably don't need to use this. +// Runs in constant time based on length of the keys. +func (privKey PrivKeySecp256k1) Equals(other PrivKey) bool { + if otherSecp, ok := other.(PrivKeySecp256k1); ok { + return subtle.ConstantTimeCompare(privKey[:], otherSecp[:]) == 1 + } else { + return false + } +} + +/* +// Deterministically generates new priv-key bytes from key. +func (key PrivKeySecp256k1) Generate(index int) PrivKeySecp256k1 { + newBytes := cdc.BinarySha256(struct { + PrivKey [64]byte + Index int + }{key, index}) + var newKey [64]byte + copy(newKey[:], newBytes) + return PrivKeySecp256k1(newKey) +} +*/ + +func GenPrivKeySecp256k1() PrivKeySecp256k1 { + privKeyBytes := [32]byte{} + copy(privKeyBytes[:], CRandBytes(32)) + priv, _ := secp256k1.PrivKeyFromBytes(secp256k1.S256(), privKeyBytes[:]) + copy(privKeyBytes[:], priv.Serialize()) + return PrivKeySecp256k1(privKeyBytes) +} + +// NOTE: secret should be the output of a KDF like bcrypt, +// if it's derived from user input. +func GenPrivKeySecp256k1FromSecret(secret []byte) PrivKeySecp256k1 { + privKey32 := Sha256(secret) // Not Ripemd160 because we want 32 bytes. + priv, _ := secp256k1.PrivKeyFromBytes(secp256k1.S256(), privKey32) + privKeyBytes := [32]byte{} + copy(privKeyBytes[:], priv.Serialize()) + return PrivKeySecp256k1(privKeyBytes) +} diff --git a/crypto/priv_key_test.go b/crypto/priv_key_test.go new file mode 100644 index 000000000..ab56ebad2 --- /dev/null +++ b/crypto/priv_key_test.go @@ -0,0 +1,60 @@ +package crypto_test + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/tendermint/tendermint/crypto" +) + +func TestGeneratePrivKey(t *testing.T) { + testPriv := crypto.GenPrivKeyEd25519() + testGenerate := testPriv.Generate(1) + signBytes := []byte("something to sign") + pub := testGenerate.PubKey() + sig, err := testGenerate.Sign(signBytes) + assert.NoError(t, err) + assert.True(t, pub.VerifyBytes(signBytes, sig)) +} + +/* + +type BadKey struct { + PrivKeyEd25519 +} + +func TestReadPrivKey(t *testing.T) { + assert, require := assert.New(t), require.New(t) + + // garbage in, garbage out + garbage := []byte("hjgewugfbiewgofwgewr") + XXX This test wants to register BadKey globally to go-crypto, + but we don't want to support that. + _, err := PrivKeyFromBytes(garbage) + require.Error(err) + + edKey := GenPrivKeyEd25519() + badKey := BadKey{edKey} + + cases := []struct { + key PrivKey + valid bool + }{ + {edKey, true}, + {badKey, false}, + } + + for i, tc := range cases { + data := tc.key.Bytes() + fmt.Println(">>>", data) + key, err := PrivKeyFromBytes(data) + fmt.Printf("!!! %#v\n", key, err) + if tc.valid { + assert.NoError(err, "%d", i) + assert.Equal(tc.key, key, "%d", i) + } else { + assert.Error(err, "%d: %#v", i, key) + } + } +} +*/ diff --git a/crypto/pub_key.go b/crypto/pub_key.go new file mode 100644 index 000000000..51ef6c54e --- /dev/null +++ b/crypto/pub_key.go @@ -0,0 +1,149 @@ +package crypto + +import ( + "bytes" + "crypto/sha256" + "fmt" + + "golang.org/x/crypto/ripemd160" + + secp256k1 "github.com/btcsuite/btcd/btcec" + + "github.com/tendermint/ed25519" + "github.com/tendermint/ed25519/extra25519" + + cmn "github.com/tendermint/tmlibs/common" + + "github.com/tendermint/tendermint/crypto/tmhash" +) + +// An address is a []byte, but hex-encoded even in JSON. +// []byte leaves us the option to change the address length. +// Use an alias so Unmarshal methods (with ptr receivers) are available too. +type Address = cmn.HexBytes + +func PubKeyFromBytes(pubKeyBytes []byte) (pubKey PubKey, err error) { + err = cdc.UnmarshalBinaryBare(pubKeyBytes, &pubKey) + return +} + +//---------------------------------------- + +type PubKey interface { + Address() Address + Bytes() []byte + VerifyBytes(msg []byte, sig Signature) bool + Equals(PubKey) bool +} + +//------------------------------------- + +var _ PubKey = PubKeyEd25519{} + +// Implements PubKeyInner +type PubKeyEd25519 [32]byte + +// Address is the SHA256-20 of the raw pubkey bytes. +func (pubKey PubKeyEd25519) Address() Address { + return Address(tmhash.Sum(pubKey[:])) +} + +func (pubKey PubKeyEd25519) Bytes() []byte { + bz, err := cdc.MarshalBinaryBare(pubKey) + if err != nil { + panic(err) + } + return bz +} + +func (pubKey PubKeyEd25519) VerifyBytes(msg []byte, sig_ Signature) bool { + // make sure we use the same algorithm to sign + sig, ok := sig_.(SignatureEd25519) + if !ok { + return false + } + pubKeyBytes := [32]byte(pubKey) + sigBytes := [64]byte(sig) + return ed25519.Verify(&pubKeyBytes, msg, &sigBytes) +} + +// For use with golang/crypto/nacl/box +// If error, returns nil. +func (pubKey PubKeyEd25519) ToCurve25519() *[32]byte { + keyCurve25519, pubKeyBytes := new([32]byte), [32]byte(pubKey) + ok := extra25519.PublicKeyToCurve25519(keyCurve25519, &pubKeyBytes) + if !ok { + return nil + } + return keyCurve25519 +} + +func (pubKey PubKeyEd25519) String() string { + return fmt.Sprintf("PubKeyEd25519{%X}", pubKey[:]) +} + +func (pubKey PubKeyEd25519) Equals(other PubKey) bool { + if otherEd, ok := other.(PubKeyEd25519); ok { + return bytes.Equal(pubKey[:], otherEd[:]) + } else { + return false + } +} + +//------------------------------------- + +var _ PubKey = PubKeySecp256k1{} + +// Implements PubKey. +// Compressed pubkey (just the x-cord), +// prefixed with 0x02 or 0x03, depending on the y-cord. +type PubKeySecp256k1 [33]byte + +// Implements Bitcoin style addresses: RIPEMD160(SHA256(pubkey)) +func (pubKey PubKeySecp256k1) Address() Address { + hasherSHA256 := sha256.New() + hasherSHA256.Write(pubKey[:]) // does not error + sha := hasherSHA256.Sum(nil) + + hasherRIPEMD160 := ripemd160.New() + hasherRIPEMD160.Write(sha) // does not error + return Address(hasherRIPEMD160.Sum(nil)) +} + +func (pubKey PubKeySecp256k1) Bytes() []byte { + bz, err := cdc.MarshalBinaryBare(pubKey) + if err != nil { + panic(err) + } + return bz +} + +func (pubKey PubKeySecp256k1) VerifyBytes(msg []byte, sig_ Signature) bool { + // and assert same algorithm to sign and verify + sig, ok := sig_.(SignatureSecp256k1) + if !ok { + return false + } + + pub__, err := secp256k1.ParsePubKey(pubKey[:], secp256k1.S256()) + if err != nil { + return false + } + sig__, err := secp256k1.ParseDERSignature(sig[:], secp256k1.S256()) + if err != nil { + return false + } + return sig__.Verify(Sha256(msg), pub__) +} + +func (pubKey PubKeySecp256k1) String() string { + return fmt.Sprintf("PubKeySecp256k1{%X}", pubKey[:]) +} + +func (pubKey PubKeySecp256k1) Equals(other PubKey) bool { + if otherSecp, ok := other.(PubKeySecp256k1); ok { + return bytes.Equal(pubKey[:], otherSecp[:]) + } else { + return false + } +} diff --git a/crypto/pub_key_test.go b/crypto/pub_key_test.go new file mode 100644 index 000000000..7b856cf18 --- /dev/null +++ b/crypto/pub_key_test.go @@ -0,0 +1,50 @@ +package crypto + +import ( + "encoding/hex" + "testing" + + "github.com/btcsuite/btcutil/base58" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +type keyData struct { + priv string + pub string + addr string +} + +var secpDataTable = []keyData{ + { + priv: "a96e62ed3955e65be32703f12d87b6b5cf26039ecfa948dc5107a495418e5330", + pub: "02950e1cdfcb133d6024109fd489f734eeb4502418e538c28481f22bce276f248c", + addr: "1CKZ9Nx4zgds8tU7nJHotKSDr4a9bYJCa3", + }, +} + +func TestPubKeySecp256k1Address(t *testing.T) { + for _, d := range secpDataTable { + privB, _ := hex.DecodeString(d.priv) + pubB, _ := hex.DecodeString(d.pub) + addrBbz, _, _ := base58.CheckDecode(d.addr) + addrB := Address(addrBbz) + + var priv PrivKeySecp256k1 + copy(priv[:], privB) + + pubKey := priv.PubKey() + pubT, _ := pubKey.(PubKeySecp256k1) + pub := pubT[:] + addr := pubKey.Address() + + assert.Equal(t, pub, pubB, "Expected pub keys to match") + assert.Equal(t, addr, addrB, "Expected addresses to match") + } +} + +func TestPubKeyInvalidDataProperReturnsEmpty(t *testing.T) { + pk, err := PubKeyFromBytes([]byte("foo")) + require.NotNil(t, err, "expecting a non-nil error") + require.Nil(t, pk, "expecting an empty public key on error") +} diff --git a/crypto/random.go b/crypto/random.go new file mode 100644 index 000000000..66da035a9 --- /dev/null +++ b/crypto/random.go @@ -0,0 +1,108 @@ +package crypto + +import ( + "crypto/aes" + "crypto/cipher" + crand "crypto/rand" + "crypto/sha256" + "encoding/hex" + "io" + "sync" + + . "github.com/tendermint/tmlibs/common" +) + +var gRandInfo *randInfo + +func init() { + gRandInfo = &randInfo{} + gRandInfo.MixEntropy(randBytes(32)) // Init +} + +// Mix additional bytes of randomness, e.g. from hardware, user-input, etc. +// It is OK to call it multiple times. It does not diminish security. +func MixEntropy(seedBytes []byte) { + gRandInfo.MixEntropy(seedBytes) +} + +// This only uses the OS's randomness +func randBytes(numBytes int) []byte { + b := make([]byte, numBytes) + _, err := crand.Read(b) + if err != nil { + PanicCrisis(err) + } + return b +} + +// This uses the OS and the Seed(s). +func CRandBytes(numBytes int) []byte { + b := make([]byte, numBytes) + _, err := gRandInfo.Read(b) + if err != nil { + PanicCrisis(err) + } + return b +} + +// CRandHex returns a hex encoded string that's floor(numDigits/2) * 2 long. +// +// Note: CRandHex(24) gives 96 bits of randomness that +// are usually strong enough for most purposes. +func CRandHex(numDigits int) string { + return hex.EncodeToString(CRandBytes(numDigits / 2)) +} + +// Returns a crand.Reader mixed with user-supplied entropy +func CReader() io.Reader { + return gRandInfo +} + +//-------------------------------------------------------------------------------- + +type randInfo struct { + mtx sync.Mutex + seedBytes [32]byte + cipherAES256 cipher.Block + streamAES256 cipher.Stream + reader io.Reader +} + +// You can call this as many times as you'd like. +// XXX TODO review +func (ri *randInfo) MixEntropy(seedBytes []byte) { + ri.mtx.Lock() + defer ri.mtx.Unlock() + // Make new ri.seedBytes using passed seedBytes and current ri.seedBytes: + // ri.seedBytes = sha256( seedBytes || ri.seedBytes ) + h := sha256.New() + h.Write(seedBytes) + h.Write(ri.seedBytes[:]) + hashBytes := h.Sum(nil) + hashBytes32 := [32]byte{} + copy(hashBytes32[:], hashBytes) + ri.seedBytes = xorBytes32(ri.seedBytes, hashBytes32) + // Create new cipher.Block + var err error + ri.cipherAES256, err = aes.NewCipher(ri.seedBytes[:]) + if err != nil { + PanicSanity("Error creating AES256 cipher: " + err.Error()) + } + // Create new stream + ri.streamAES256 = cipher.NewCTR(ri.cipherAES256, randBytes(aes.BlockSize)) + // Create new reader + ri.reader = &cipher.StreamReader{S: ri.streamAES256, R: crand.Reader} +} + +func (ri *randInfo) Read(b []byte) (n int, err error) { + ri.mtx.Lock() + defer ri.mtx.Unlock() + return ri.reader.Read(b) +} + +func xorBytes32(bytesA [32]byte, bytesB [32]byte) (res [32]byte) { + for i, b := range bytesA { + res[i] = b ^ bytesB[i] + } + return res +} diff --git a/crypto/signature.go b/crypto/signature.go new file mode 100644 index 000000000..1ffb45ea3 --- /dev/null +++ b/crypto/signature.go @@ -0,0 +1,88 @@ +package crypto + +import ( + "fmt" + + "crypto/subtle" + + . "github.com/tendermint/tmlibs/common" +) + +func SignatureFromBytes(pubKeyBytes []byte) (pubKey Signature, err error) { + err = cdc.UnmarshalBinaryBare(pubKeyBytes, &pubKey) + return +} + +//---------------------------------------- + +type Signature interface { + Bytes() []byte + IsZero() bool + Equals(Signature) bool +} + +//------------------------------------- + +var _ Signature = SignatureEd25519{} + +// Implements Signature +type SignatureEd25519 [64]byte + +func (sig SignatureEd25519) Bytes() []byte { + bz, err := cdc.MarshalBinaryBare(sig) + if err != nil { + panic(err) + } + return bz +} + +func (sig SignatureEd25519) IsZero() bool { return len(sig) == 0 } + +func (sig SignatureEd25519) String() string { return fmt.Sprintf("/%X.../", Fingerprint(sig[:])) } + +func (sig SignatureEd25519) Equals(other Signature) bool { + if otherEd, ok := other.(SignatureEd25519); ok { + return subtle.ConstantTimeCompare(sig[:], otherEd[:]) == 1 + } else { + return false + } +} + +func SignatureEd25519FromBytes(data []byte) Signature { + var sig SignatureEd25519 + copy(sig[:], data) + return sig +} + +//------------------------------------- + +var _ Signature = SignatureSecp256k1{} + +// Implements Signature +type SignatureSecp256k1 []byte + +func (sig SignatureSecp256k1) Bytes() []byte { + bz, err := cdc.MarshalBinaryBare(sig) + if err != nil { + panic(err) + } + return bz +} + +func (sig SignatureSecp256k1) IsZero() bool { return len(sig) == 0 } + +func (sig SignatureSecp256k1) String() string { return fmt.Sprintf("/%X.../", Fingerprint(sig[:])) } + +func (sig SignatureSecp256k1) Equals(other Signature) bool { + if otherSecp, ok := other.(SignatureSecp256k1); ok { + return subtle.ConstantTimeCompare(sig[:], otherSecp[:]) == 1 + } else { + return false + } +} + +func SignatureSecp256k1FromBytes(data []byte) Signature { + sig := make(SignatureSecp256k1, len(data)) + copy(sig[:], data) + return sig +} diff --git a/crypto/signature_test.go b/crypto/signature_test.go new file mode 100644 index 000000000..d6ae2b7a9 --- /dev/null +++ b/crypto/signature_test.go @@ -0,0 +1,46 @@ +package crypto + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestSignAndValidateEd25519(t *testing.T) { + + privKey := GenPrivKeyEd25519() + pubKey := privKey.PubKey() + + msg := CRandBytes(128) + sig, err := privKey.Sign(msg) + require.Nil(t, err) + + // Test the signature + assert.True(t, pubKey.VerifyBytes(msg, sig)) + + // Mutate the signature, just one bit. + sigEd := sig.(SignatureEd25519) + sigEd[7] ^= byte(0x01) + sig = sigEd + + assert.False(t, pubKey.VerifyBytes(msg, sig)) +} + +func TestSignAndValidateSecp256k1(t *testing.T) { + privKey := GenPrivKeySecp256k1() + pubKey := privKey.PubKey() + + msg := CRandBytes(128) + sig, err := privKey.Sign(msg) + require.Nil(t, err) + + assert.True(t, pubKey.VerifyBytes(msg, sig)) + + // Mutate the signature, just one bit. + sigEd := sig.(SignatureSecp256k1) + sigEd[3] ^= byte(0x01) + sig = sigEd + + assert.False(t, pubKey.VerifyBytes(msg, sig)) +} diff --git a/crypto/symmetric.go b/crypto/symmetric.go new file mode 100644 index 000000000..d4ac9b55b --- /dev/null +++ b/crypto/symmetric.go @@ -0,0 +1,51 @@ +package crypto + +import ( + "errors" + + . "github.com/tendermint/tmlibs/common" + "golang.org/x/crypto/nacl/secretbox" +) + +const nonceLen = 24 +const secretLen = 32 + +// secret must be 32 bytes long. Use something like Sha256(Bcrypt(passphrase)) +// The ciphertext is (secretbox.Overhead + 24) bytes longer than the plaintext. +// NOTE: call crypto.MixEntropy() first. +func EncryptSymmetric(plaintext []byte, secret []byte) (ciphertext []byte) { + if len(secret) != secretLen { + PanicSanity(Fmt("Secret must be 32 bytes long, got len %v", len(secret))) + } + nonce := CRandBytes(nonceLen) + nonceArr := [nonceLen]byte{} + copy(nonceArr[:], nonce) + secretArr := [secretLen]byte{} + copy(secretArr[:], secret) + ciphertext = make([]byte, nonceLen+secretbox.Overhead+len(plaintext)) + copy(ciphertext, nonce) + secretbox.Seal(ciphertext[nonceLen:nonceLen], plaintext, &nonceArr, &secretArr) + return ciphertext +} + +// secret must be 32 bytes long. Use something like Sha256(Bcrypt(passphrase)) +// The ciphertext is (secretbox.Overhead + 24) bytes longer than the plaintext. +func DecryptSymmetric(ciphertext []byte, secret []byte) (plaintext []byte, err error) { + if len(secret) != secretLen { + PanicSanity(Fmt("Secret must be 32 bytes long, got len %v", len(secret))) + } + if len(ciphertext) <= secretbox.Overhead+nonceLen { + return nil, errors.New("Ciphertext is too short") + } + nonce := ciphertext[:nonceLen] + nonceArr := [nonceLen]byte{} + copy(nonceArr[:], nonce) + secretArr := [secretLen]byte{} + copy(secretArr[:], secret) + plaintext = make([]byte, len(ciphertext)-nonceLen-secretbox.Overhead) + _, ok := secretbox.Open(plaintext[:0], ciphertext[nonceLen:], &nonceArr, &secretArr) + if !ok { + return nil, errors.New("Ciphertext decryption failed") + } + return plaintext, nil +} diff --git a/crypto/symmetric_test.go b/crypto/symmetric_test.go new file mode 100644 index 000000000..d92bff1aa --- /dev/null +++ b/crypto/symmetric_test.go @@ -0,0 +1,42 @@ +package crypto + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "golang.org/x/crypto/bcrypt" +) + +func TestSimple(t *testing.T) { + + MixEntropy([]byte("someentropy")) + + plaintext := []byte("sometext") + secret := []byte("somesecretoflengththirtytwo===32") + ciphertext := EncryptSymmetric(plaintext, secret) + plaintext2, err := DecryptSymmetric(ciphertext, secret) + + require.Nil(t, err, "%+v", err) + assert.Equal(t, plaintext, plaintext2) +} + +func TestSimpleWithKDF(t *testing.T) { + + MixEntropy([]byte("someentropy")) + + plaintext := []byte("sometext") + secretPass := []byte("somesecret") + secret, err := bcrypt.GenerateFromPassword(secretPass, 12) + if err != nil { + t.Error(err) + } + secret = Sha256(secret) + + ciphertext := EncryptSymmetric(plaintext, secret) + plaintext2, err := DecryptSymmetric(ciphertext, secret) + + require.Nil(t, err, "%+v", err) + assert.Equal(t, plaintext, plaintext2) +} diff --git a/crypto/tmhash/hash.go b/crypto/tmhash/hash.go new file mode 100644 index 000000000..1b29d8680 --- /dev/null +++ b/crypto/tmhash/hash.go @@ -0,0 +1,48 @@ +package tmhash + +import ( + "crypto/sha256" + "hash" +) + +const ( + Size = 20 + BlockSize = sha256.BlockSize +) + +type sha256trunc struct { + sha256 hash.Hash +} + +func (h sha256trunc) Write(p []byte) (n int, err error) { + return h.sha256.Write(p) +} +func (h sha256trunc) Sum(b []byte) []byte { + shasum := h.sha256.Sum(b) + return shasum[:Size] +} + +func (h sha256trunc) Reset() { + h.sha256.Reset() +} + +func (h sha256trunc) Size() int { + return Size +} + +func (h sha256trunc) BlockSize() int { + return h.sha256.BlockSize() +} + +// New returns a new hash.Hash. +func New() hash.Hash { + return sha256trunc{ + sha256: sha256.New(), + } +} + +// Sum returns the first 20 bytes of SHA256 of the bz. +func Sum(bz []byte) []byte { + hash := sha256.Sum256(bz) + return hash[:Size] +} diff --git a/crypto/tmhash/hash_test.go b/crypto/tmhash/hash_test.go new file mode 100644 index 000000000..27938039a --- /dev/null +++ b/crypto/tmhash/hash_test.go @@ -0,0 +1,23 @@ +package tmhash_test + +import ( + "crypto/sha256" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/tendermint/tendermint/crypto/tmhash" +) + +func TestHash(t *testing.T) { + testVector := []byte("abc") + hasher := tmhash.New() + hasher.Write(testVector) + bz := hasher.Sum(nil) + + hasher = sha256.New() + hasher.Write(testVector) + bz2 := hasher.Sum(nil) + bz2 = bz2[:20] + + assert.Equal(t, bz, bz2) +} diff --git a/crypto/version.go b/crypto/version.go new file mode 100644 index 000000000..77c0bed8a --- /dev/null +++ b/crypto/version.go @@ -0,0 +1,3 @@ +package crypto + +const Version = "0.9.0-dev" diff --git a/docs/examples/init_testnet.sh b/docs/examples/init_testnet.sh index cd83751ec..84e54674c 100644 --- a/docs/examples/init_testnet.sh +++ b/docs/examples/init_testnet.sh @@ -30,7 +30,7 @@ echo "{ \"validators\": [ { \"pub_key\": { - \"type\": \"AC26791624DE60\", + \"type\": \"tendermint/PubKeyEd25519\", \"value\": $value0 }, \"power:\": 10, @@ -38,7 +38,7 @@ echo "{ }, { \"pub_key\": { - \"type\": \"AC26791624DE60\", + \"type\": \"tendermint/PubKeyEd25519\", \"value\": $value1 }, \"power:\": 10, @@ -46,7 +46,7 @@ echo "{ }, { \"pub_key\": { - \"type\": \"AC26791624DE60\", + \"type\": \"tendermint/PubKeyEd25519\", \"value\": $value2 }, \"power:\": 10, @@ -54,7 +54,7 @@ echo "{ }, { \"pub_key\": { - \"type\": \"AC26791624DE60\", + \"type\": \"tendermint/PubKeyEd25519\", \"value\": $value3 }, \"power:\": 10, @@ -66,4 +66,4 @@ echo "{ cp $file0 $file1 cp $file0 $file2 -cp $file2 $file3 \ No newline at end of file +cp $file2 $file3 diff --git a/docs/examples/node0/config/genesis.json b/docs/examples/node0/config/genesis.json index b9c12e31b..ac306bd2f 100644 --- a/docs/examples/node0/config/genesis.json +++ b/docs/examples/node0/config/genesis.json @@ -4,34 +4,34 @@ "validators": [ { "pub_key": { - "type": "AC26791624DE60", + "type": "tendermint/PubKeyEd25519", "value": "D+k4AdjnYPWbB9wmad137Bdpo/kAulOoTRQrLy/Qc4k=" }, - "power": 10, + "power": "10", "name": "" }, { "pub_key": { - "type": "AC26791624DE60", + "type": "tendermint/PubKeyEd25519", "value": "b56N5GCR1adcVRuENjfKw/mrm2dkhT7wNZXV/SDsKsU=" }, - "power": 10, + "power": "10", "name": "" }, { "pub_key": { - "type": "AC26791624DE60", + "type": "tendermint/PubKeyEd25519", "value": "IgZDpJvGA0TAamicA8ircy+RX/BkUlj6DXwM791ywIU=" }, - "power": 10, + "power": "10", "name": "" }, { "pub_key": { - "type": "AC26791624DE60", + "type": "tendermint/PubKeyEd25519", "value": "KGAZfxZvIZ7abbeIQ85U1ECG6+I62KSdaH8ulc0+OiU=" }, - "power": 10, + "power": "10", "name": "" } ], diff --git a/docs/examples/node0/config/node_key.json b/docs/examples/node0/config/node_key.json index f4cdd093f..dec1fd42d 100644 --- a/docs/examples/node0/config/node_key.json +++ b/docs/examples/node0/config/node_key.json @@ -1 +1 @@ -{"priv_key":{"type":"954568A3288910","value":"7lY+k6EDllG8Q9gVbF5313t/ag2YGkBVKdVa0YHJ9xO5k0w3Q/hke0Z7UFT1KgVDGRUEKzwAwwjwFQUvgF0ZWg=="}} \ No newline at end of file +{"priv_key":{"type":"tendermint/PrivKeyEd25519","value":"7lY+k6EDllG8Q9gVbF5313t/ag2YGkBVKdVa0YHJ9xO5k0w3Q/hke0Z7UFT1KgVDGRUEKzwAwwjwFQUvgF0ZWg=="}} diff --git a/docs/examples/node0/config/priv_validator.json b/docs/examples/node0/config/priv_validator.json index e758b75b8..ef2daccbb 100644 --- a/docs/examples/node0/config/priv_validator.json +++ b/docs/examples/node0/config/priv_validator.json @@ -1,14 +1,14 @@ { "address": "122A9414774A2FCAD026201DA477EF3F41970EF0", "pub_key": { - "type": "AC26791624DE60", + "type": "tendermint/PubKeyEd25519", "value": "D+k4AdjnYPWbB9wmad137Bdpo/kAulOoTRQrLy/Qc4k=" }, - "last_height": 0, - "last_round": 0, + "last_height": "0", + "last_round": "0", "last_step": 0, "priv_key": { - "type": "954568A3288910", + "type": "tendermint/PrivKeyEd25519", "value": "YLxp3ho+kySgAnzjBptbxDzSGw2ntGZLsIHQsaVxY/cP6TgB2Odg9ZsH3CZp3XfsF2mj+QC6U6hNFCsvL9BziQ==" } -} \ No newline at end of file +} diff --git a/docs/examples/node1/config/genesis.json b/docs/examples/node1/config/genesis.json index b9c12e31b..ac306bd2f 100644 --- a/docs/examples/node1/config/genesis.json +++ b/docs/examples/node1/config/genesis.json @@ -4,34 +4,34 @@ "validators": [ { "pub_key": { - "type": "AC26791624DE60", + "type": "tendermint/PubKeyEd25519", "value": "D+k4AdjnYPWbB9wmad137Bdpo/kAulOoTRQrLy/Qc4k=" }, - "power": 10, + "power": "10", "name": "" }, { "pub_key": { - "type": "AC26791624DE60", + "type": "tendermint/PubKeyEd25519", "value": "b56N5GCR1adcVRuENjfKw/mrm2dkhT7wNZXV/SDsKsU=" }, - "power": 10, + "power": "10", "name": "" }, { "pub_key": { - "type": "AC26791624DE60", + "type": "tendermint/PubKeyEd25519", "value": "IgZDpJvGA0TAamicA8ircy+RX/BkUlj6DXwM791ywIU=" }, - "power": 10, + "power": "10", "name": "" }, { "pub_key": { - "type": "AC26791624DE60", + "type": "tendermint/PubKeyEd25519", "value": "KGAZfxZvIZ7abbeIQ85U1ECG6+I62KSdaH8ulc0+OiU=" }, - "power": 10, + "power": "10", "name": "" } ], diff --git a/docs/examples/node1/config/node_key.json b/docs/examples/node1/config/node_key.json index 374efe63b..05f4ea846 100644 --- a/docs/examples/node1/config/node_key.json +++ b/docs/examples/node1/config/node_key.json @@ -1 +1 @@ -{"priv_key":{"type":"954568A3288910","value":"H71dc/TIG7nTselfa9nG0WRArXLKYnm7P5eFCk2lk8ASKQ3sIHpbdxCSHQD/RcdHe7TiabJeuOssNPvPWiyQEQ=="}} \ No newline at end of file +{"priv_key":{"type":"tendermint/PrivKeyEd25519","value":"H71dc/TIG7nTselfa9nG0WRArXLKYnm7P5eFCk2lk8ASKQ3sIHpbdxCSHQD/RcdHe7TiabJeuOssNPvPWiyQEQ=="}} diff --git a/docs/examples/node1/config/priv_validator.json b/docs/examples/node1/config/priv_validator.json index caf3dbc59..3a38793e4 100644 --- a/docs/examples/node1/config/priv_validator.json +++ b/docs/examples/node1/config/priv_validator.json @@ -1,14 +1,14 @@ { "address": "BEA1B57F5806CF9AC4D54C8CF806DED5C0F102E1", "pub_key": { - "type": "AC26791624DE60", + "type": "tendermint/PubKeyEd25519", "value": "b56N5GCR1adcVRuENjfKw/mrm2dkhT7wNZXV/SDsKsU=" }, - "last_height": 0, - "last_round": 0, + "last_height": "0", + "last_round": "0", "last_step": 0, "priv_key": { - "type": "954568A3288910", + "type": "tendermint/PrivKeyEd25519", "value": "o0IqrHSPtd5YqGefodWxpJuRzvuVBjgbH785vbMgk7Vvno3kYJHVp1xVG4Q2N8rD+aubZ2SFPvA1ldX9IOwqxQ==" } -} \ No newline at end of file +} diff --git a/docs/examples/node2/config/genesis.json b/docs/examples/node2/config/genesis.json index b9c12e31b..ac306bd2f 100644 --- a/docs/examples/node2/config/genesis.json +++ b/docs/examples/node2/config/genesis.json @@ -4,34 +4,34 @@ "validators": [ { "pub_key": { - "type": "AC26791624DE60", + "type": "tendermint/PubKeyEd25519", "value": "D+k4AdjnYPWbB9wmad137Bdpo/kAulOoTRQrLy/Qc4k=" }, - "power": 10, + "power": "10", "name": "" }, { "pub_key": { - "type": "AC26791624DE60", + "type": "tendermint/PubKeyEd25519", "value": "b56N5GCR1adcVRuENjfKw/mrm2dkhT7wNZXV/SDsKsU=" }, - "power": 10, + "power": "10", "name": "" }, { "pub_key": { - "type": "AC26791624DE60", + "type": "tendermint/PubKeyEd25519", "value": "IgZDpJvGA0TAamicA8ircy+RX/BkUlj6DXwM791ywIU=" }, - "power": 10, + "power": "10", "name": "" }, { "pub_key": { - "type": "AC26791624DE60", + "type": "tendermint/PubKeyEd25519", "value": "KGAZfxZvIZ7abbeIQ85U1ECG6+I62KSdaH8ulc0+OiU=" }, - "power": 10, + "power": "10", "name": "" } ], diff --git a/docs/examples/node2/config/node_key.json b/docs/examples/node2/config/node_key.json index 52a978bb0..6f15a541b 100644 --- a/docs/examples/node2/config/node_key.json +++ b/docs/examples/node2/config/node_key.json @@ -1 +1 @@ -{"priv_key":{"type":"954568A3288910","value":"COHZ/Y2cWGWxJNkRwtpQBt5sYvOnb6Gpz0lO46XERRJFBIdSWD5x1UMGRSTmnvW1ec5G4bMdg6zUZKOZD+vVPg=="}} \ No newline at end of file +{"priv_key":{"type":"tendermint/PrivKeyEd25519","value":"COHZ/Y2cWGWxJNkRwtpQBt5sYvOnb6Gpz0lO46XERRJFBIdSWD5x1UMGRSTmnvW1ec5G4bMdg6zUZKOZD+vVPg=="}} diff --git a/docs/examples/node2/config/priv_validator.json b/docs/examples/node2/config/priv_validator.json index 65fa30484..2bcd31a76 100644 --- a/docs/examples/node2/config/priv_validator.json +++ b/docs/examples/node2/config/priv_validator.json @@ -1,14 +1,14 @@ { "address": "F0AA266949FB29ADA0B679C27889ED930BD1BDA1", "pub_key": { - "type": "AC26791624DE60", + "type": "tendermint/PubKeyEd25519", "value": "IgZDpJvGA0TAamicA8ircy+RX/BkUlj6DXwM791ywIU=" }, - "last_height": 0, - "last_round": 0, + "last_height": "0", + "last_round": "0", "last_step": 0, "priv_key": { - "type": "954568A3288910", + "type": "tendermint/PrivKeyEd25519", "value": "khADeZ5K/8u/L99DFaZNRq8V5g+EHWbwfqFjhCrppaAiBkOkm8YDRMBqaJwDyKtzL5Ff8GRSWPoNfAzv3XLAhQ==" } -} \ No newline at end of file +} diff --git a/docs/examples/node3/config/genesis.json b/docs/examples/node3/config/genesis.json index b9c12e31b..ac306bd2f 100644 --- a/docs/examples/node3/config/genesis.json +++ b/docs/examples/node3/config/genesis.json @@ -4,34 +4,34 @@ "validators": [ { "pub_key": { - "type": "AC26791624DE60", + "type": "tendermint/PubKeyEd25519", "value": "D+k4AdjnYPWbB9wmad137Bdpo/kAulOoTRQrLy/Qc4k=" }, - "power": 10, + "power": "10", "name": "" }, { "pub_key": { - "type": "AC26791624DE60", + "type": "tendermint/PubKeyEd25519", "value": "b56N5GCR1adcVRuENjfKw/mrm2dkhT7wNZXV/SDsKsU=" }, - "power": 10, + "power": "10", "name": "" }, { "pub_key": { - "type": "AC26791624DE60", + "type": "tendermint/PubKeyEd25519", "value": "IgZDpJvGA0TAamicA8ircy+RX/BkUlj6DXwM791ywIU=" }, - "power": 10, + "power": "10", "name": "" }, { "pub_key": { - "type": "AC26791624DE60", + "type": "tendermint/PubKeyEd25519", "value": "KGAZfxZvIZ7abbeIQ85U1ECG6+I62KSdaH8ulc0+OiU=" }, - "power": 10, + "power": "10", "name": "" } ], diff --git a/docs/examples/node3/config/node_key.json b/docs/examples/node3/config/node_key.json index bde4e0ede..01a14a3bf 100644 --- a/docs/examples/node3/config/node_key.json +++ b/docs/examples/node3/config/node_key.json @@ -1 +1 @@ -{"priv_key":{"type":"954568A3288910","value":"9Y9xp/tUJJ6pHTF5SUV0bGKYSdVbFtMHu+Lr8S0JBSZAwneaejnfOEU1LMKOnQ07skrDUaJcj5di3jAyjxJzqg=="}} \ No newline at end of file +{"priv_key":{"type":"tendermint/PrivKeyEd25519","value":"9Y9xp/tUJJ6pHTF5SUV0bGKYSdVbFtMHu+Lr8S0JBSZAwneaejnfOEU1LMKOnQ07skrDUaJcj5di3jAyjxJzqg=="}} diff --git a/docs/examples/node3/config/priv_validator.json b/docs/examples/node3/config/priv_validator.json index 1d985a00b..bc8a66513 100644 --- a/docs/examples/node3/config/priv_validator.json +++ b/docs/examples/node3/config/priv_validator.json @@ -1,14 +1,14 @@ { "address": "9A1A6914EB5F4FF0269C7EEEE627C27310CC64F9", "pub_key": { - "type": "AC26791624DE60", + "type": "tendermint/PubKeyEd25519", "value": "KGAZfxZvIZ7abbeIQ85U1ECG6+I62KSdaH8ulc0+OiU=" }, - "last_height": 0, - "last_round": 0, + "last_height": "0", + "last_round": "0", "last_step": 0, "priv_key": { - "type": "954568A3288910", + "type": "tendermint/PrivKeyEd25519", "value": "jb52LZ5gp+eQ8nJlFK1z06nBMp1gD8ICmyzdM1icGOgoYBl/Fm8hntptt4hDzlTUQIbr4jrYpJ1ofy6VzT46JQ==" } -} \ No newline at end of file +} diff --git a/docs/running-in-production.md b/docs/running-in-production.md index 7e6068d4b..dc60c618d 100644 --- a/docs/running-in-production.md +++ b/docs/running-in-production.md @@ -21,7 +21,7 @@ to prevent Denial-of-service attacks. You can read more about it ### P2P The core of the Tendermint peer-to-peer system is `MConnection`. Each -connection has `MaxPacketMsgPayloadSize`, which is the maximum packet +connection has `MaxPacketMsgSize`, which is the maximum packet size and bounded send & receive queues. One can impose restrictions on send & receive rate per connection (`SendRate`, `RecvRate`). diff --git a/docs/spec/blockchain/encoding.md b/docs/spec/blockchain/encoding.md index aa1842107..e59d3c8ce 100644 --- a/docs/spec/blockchain/encoding.md +++ b/docs/spec/blockchain/encoding.md @@ -249,7 +249,7 @@ For instance, an ED25519 PubKey would look like: ``` { - "type": "AC26791624DE60", + "type": "tendermint/PubKeyEd25519", "value": "uZ4h63OFWuQ36ZZ4Bd6NF+/w9fWUwrOncrQsackrsTk=" } ``` diff --git a/docs/spec/scripts/crypto.go b/docs/spec/scripts/crypto.go index e4dbd8a24..aeca07eeb 100644 --- a/docs/spec/scripts/crypto.go +++ b/docs/spec/scripts/crypto.go @@ -3,7 +3,7 @@ package main import ( "fmt" - crypto "github.com/tendermint/go-crypto" + "github.com/tendermint/tendermint/crypto" ) // SECRET @@ -12,7 +12,11 @@ var SECRET = []byte("some secret") func printEd() { priv := crypto.GenPrivKeyEd25519FromSecret(SECRET) pub := priv.PubKey().(crypto.PubKeyEd25519) - sig := priv.Sign([]byte("hello")).(crypto.SignatureEd25519) + sigV, err := priv.Sign([]byte("hello")) + if err != nil { + fmt.Println("Unexpected error:", err) + } + sig := sigV.(crypto.SignatureEd25519) name := "tendermint/PubKeyEd25519" length := len(pub[:]) @@ -66,7 +70,11 @@ func printEd() { func printSecp() { priv := crypto.GenPrivKeySecp256k1FromSecret(SECRET) pub := priv.PubKey().(crypto.PubKeySecp256k1) - sig := priv.Sign([]byte("hello")).(crypto.SignatureSecp256k1) + sigV, err := priv.Sign([]byte("hello")) + if err != nil { + fmt.Println("Unexpected error:", err) + } + sig := sigV.(crypto.SignatureSecp256k1) name := "tendermint/PubKeySecp256k1" length := len(pub[:]) diff --git a/docs/using-tendermint.md b/docs/using-tendermint.md index 86ec2529a..e645b48bf 100644 --- a/docs/using-tendermint.md +++ b/docs/using-tendermint.md @@ -214,7 +214,7 @@ When `tendermint init` is run, both a `genesis.json` and { "pub_key" : { "value" : "h3hk+QE8c6QLTySp8TcfzclJw/BG79ziGB/pIA+DfPE=", - "type" : "AC26791624DE60" + "type" : "tendermint/PubKeyEd25519" }, "power" : 10, "name" : "" @@ -229,16 +229,16 @@ And the `priv_validator.json`: { "last_step" : 0, - "last_round" : 0, + "last_round" : "0", "address" : "B788DEDE4F50AD8BC9462DE76741CCAFF87D51E2", "pub_key" : { "value" : "h3hk+QE8c6QLTySp8TcfzclJw/BG79ziGB/pIA+DfPE=", - "type" : "AC26791624DE60" + "type" : "tendermint/PubKeyEd25519" }, - "last_height" : 0, + "last_height" : "0", "priv_key" : { "value" : "JPivl82x+LfVkp8i3ztoTjY6c6GJ4pBxQexErOCyhwqHeGT5ATxzpAtPJKnxNx/NyUnD8Ebv3OIYH+kgD4N88Q==", - "type" : "954568A3288910" + "type" : "tendermint/PrivKeyEd25519" } } @@ -348,15 +348,15 @@ Now we can update our genesis file. For instance, if the new "address" : "5AF49D2A2D4F5AD4C7C8C4CC2FB020131E9C4902", "pub_key" : { "value" : "l9X9+fjkeBzDfPGbUM7AMIRE6uJN78zN5+lk5OYotek=", - "type" : "AC26791624DE60" + "type" : "tendermint/PubKeyEd25519" }, "priv_key" : { "value" : "EDJY9W6zlAw+su6ITgTKg2nTZcHAH1NMTW5iwlgmNDuX1f35+OR4HMN88ZtQzsAwhETq4k3vzM3n6WTk5ii16Q==", - "type" : "954568A3288910" + "type" : "tendermint/PrivKeyEd25519" }, "last_step" : 0, - "last_round" : 0, - "last_height" : 0 + "last_round" : "0", + "last_height" : "0" } then the new `genesis.json` will be: @@ -366,7 +366,7 @@ then the new `genesis.json` will be: { "pub_key" : { "value" : "h3hk+QE8c6QLTySp8TcfzclJw/BG79ziGB/pIA+DfPE=", - "type" : "AC26791624DE60" + "type" : "tendermint/PubKeyEd25519" }, "power" : 10, "name" : "" @@ -374,7 +374,7 @@ then the new `genesis.json` will be: { "pub_key" : { "value" : "l9X9+fjkeBzDfPGbUM7AMIRE6uJN78zN5+lk5OYotek=", - "type" : "AC26791624DE60" + "type" : "tendermint/PubKeyEd25519" }, "power" : 10, "name" : "" diff --git a/evidence/wire.go b/evidence/wire.go index 842e0707a..d4db37c54 100644 --- a/evidence/wire.go +++ b/evidence/wire.go @@ -2,8 +2,8 @@ package evidence import ( "github.com/tendermint/go-amino" - "github.com/tendermint/go-crypto" "github.com/tendermint/tendermint/types" + "github.com/tendermint/tendermint/crypto" ) var cdc = amino.NewCodec() diff --git a/lite/files/wire.go b/lite/files/wire.go index 99f98931e..3a207744a 100644 --- a/lite/files/wire.go +++ b/lite/files/wire.go @@ -2,7 +2,7 @@ package files import ( "github.com/tendermint/go-amino" - "github.com/tendermint/go-crypto" + "github.com/tendermint/tendermint/crypto" ) var cdc = amino.NewCodec() diff --git a/lite/helpers.go b/lite/helpers.go index 714675afb..695f6fb9b 100644 --- a/lite/helpers.go +++ b/lite/helpers.go @@ -3,7 +3,7 @@ package lite import ( "time" - crypto "github.com/tendermint/go-crypto" + crypto "github.com/tendermint/tendermint/crypto" "github.com/tendermint/tendermint/types" ) @@ -103,7 +103,13 @@ func makeVote(header *types.Header, vals *types.ValidatorSet, key crypto.PrivKey } // Sign it signBytes := vote.SignBytes(header.ChainID) - vote.Signature = key.Sign(signBytes) + // TODO Consider reworking makeVote API to return an error + sig, err := key.Sign(signBytes) + if err != nil { + panic(err) + } + vote.Signature = sig + return vote } diff --git a/node/id.go b/node/id.go index fa391f946..5100597c6 100644 --- a/node/id.go +++ b/node/id.go @@ -3,7 +3,7 @@ package node import ( "time" - "github.com/tendermint/go-crypto" + "github.com/tendermint/tendermint/crypto" ) type NodeID struct { diff --git a/node/node.go b/node/node.go index dc79cff7c..896840488 100644 --- a/node/node.go +++ b/node/node.go @@ -12,11 +12,11 @@ import ( abci "github.com/tendermint/abci/types" amino "github.com/tendermint/go-amino" - crypto "github.com/tendermint/go-crypto" cmn "github.com/tendermint/tmlibs/common" dbm "github.com/tendermint/tmlibs/db" "github.com/tendermint/tmlibs/log" + "github.com/tendermint/tendermint/crypto" bc "github.com/tendermint/tendermint/blockchain" cfg "github.com/tendermint/tendermint/config" cs "github.com/tendermint/tendermint/consensus" diff --git a/node/wire.go b/node/wire.go index a0d7677df..8b3ae8950 100644 --- a/node/wire.go +++ b/node/wire.go @@ -2,7 +2,7 @@ package node import ( amino "github.com/tendermint/go-amino" - crypto "github.com/tendermint/go-crypto" + crypto "github.com/tendermint/tendermint/crypto" ) var cdc = amino.NewCodec() diff --git a/p2p/conn/connection.go b/p2p/conn/connection.go index 5c7f19cf7..c56507296 100644 --- a/p2p/conn/connection.go +++ b/p2p/conn/connection.go @@ -18,8 +18,7 @@ import ( ) const ( - maxPacketMsgPayloadSizeDefault = 1024 // NOTE: Must be below 16,384 bytes for 14 below. - maxPacketMsgOverheadSize = 14 // NOTE: See connection_test for derivation. + defaultMaxPacketMsgSize = 1024 numBatchPacketMsgs = 10 minReadBufferSize = 1024 @@ -96,6 +95,8 @@ type MConnection struct { chStatsTimer *cmn.RepeatTimer // update channel stats periodically created time.Time // time of creation + + emptyPacketMsgSize int } // MConnConfig is a MConnection configuration. @@ -104,7 +105,7 @@ type MConnConfig struct { RecvRate int64 `mapstructure:"recv_rate"` // Maximum payload size - MaxPacketMsgPayloadSize int `mapstructure:"max_packet_msg_payload_size"` + MaxPacketMsgSize int `mapstructure:"max_packet_msg_size"` // Interval to flush writes (throttled) FlushThrottle time.Duration `mapstructure:"flush_throttle"` @@ -116,19 +117,15 @@ type MConnConfig struct { PongTimeout time.Duration `mapstructure:"pong_timeout"` } -func (cfg *MConnConfig) maxPacketMsgTotalSize() int { - return cfg.MaxPacketMsgPayloadSize + maxPacketMsgOverheadSize -} - // DefaultMConnConfig returns the default config. func DefaultMConnConfig() MConnConfig { return MConnConfig{ - SendRate: defaultSendRate, - RecvRate: defaultRecvRate, - MaxPacketMsgPayloadSize: maxPacketMsgPayloadSizeDefault, - FlushThrottle: defaultFlushThrottle, - PingInterval: defaultPingInterval, - PongTimeout: defaultPongTimeout, + SendRate: defaultSendRate, + RecvRate: defaultRecvRate, + MaxPacketMsgSize: defaultMaxPacketMsgSize, + FlushThrottle: defaultFlushThrottle, + PingInterval: defaultPingInterval, + PongTimeout: defaultPongTimeout, } } @@ -149,16 +146,17 @@ func NewMConnectionWithConfig(conn net.Conn, chDescs []*ChannelDescriptor, onRec } mconn := &MConnection{ - conn: conn, - bufConnReader: bufio.NewReaderSize(conn, minReadBufferSize), - bufConnWriter: bufio.NewWriterSize(conn, minWriteBufferSize), - sendMonitor: flow.New(0, 0), - recvMonitor: flow.New(0, 0), - send: make(chan struct{}, 1), - pong: make(chan struct{}, 1), - onReceive: onReceive, - onError: onError, - config: config, + conn: conn, + bufConnReader: bufio.NewReaderSize(conn, minReadBufferSize), + bufConnWriter: bufio.NewWriterSize(conn, minWriteBufferSize), + sendMonitor: flow.New(0, 0), + recvMonitor: flow.New(0, 0), + send: make(chan struct{}, 1), + pong: make(chan struct{}, 1), + onReceive: onReceive, + onError: onError, + config: config, + emptyPacketMsgSize: emptyPacketMsgSize(), } // Create channels @@ -399,7 +397,7 @@ func (c *MConnection) sendSomePacketMsgs() bool { // Block until .sendMonitor says we can write. // Once we're ready we send more than we asked for, // but amortized it should even out. - c.sendMonitor.Limit(c.config.maxPacketMsgTotalSize(), atomic.LoadInt64(&c.config.SendRate), true) + c.sendMonitor.Limit(c.config.MaxPacketMsgSize, atomic.LoadInt64(&c.config.SendRate), true) // Now send some PacketMsgs. for i := 0; i < numBatchPacketMsgs; i++ { @@ -457,7 +455,7 @@ func (c *MConnection) recvRoutine() { FOR_LOOP: for { // Block until .recvMonitor says we can read. - c.recvMonitor.Limit(c.config.maxPacketMsgTotalSize(), atomic.LoadInt64(&c.config.RecvRate), true) + c.recvMonitor.Limit(c.config.MaxPacketMsgSize, atomic.LoadInt64(&c.config.RecvRate), true) // Peek into bufConnReader for debugging /* @@ -477,7 +475,7 @@ FOR_LOOP: var packet Packet var _n int64 var err error - _n, err = cdc.UnmarshalBinaryReader(c.bufConnReader, &packet, int64(c.config.maxPacketMsgTotalSize())) + _n, err = cdc.UnmarshalBinaryReader(c.bufConnReader, &packet, int64(c.config.MaxPacketMsgSize)) c.recvMonitor.Update(int(_n)) if err != nil { if c.IsRunning() { @@ -633,7 +631,7 @@ func newChannel(conn *MConnection, desc ChannelDescriptor) *Channel { desc: desc, sendQueue: make(chan []byte, desc.SendQueueCapacity), recving: make([]byte, 0, desc.RecvBufferCapacity), - maxPacketMsgPayloadSize: conn.config.MaxPacketMsgPayloadSize, + maxPacketMsgPayloadSize: conn.config.MaxPacketMsgSize, } } @@ -696,7 +694,7 @@ func (ch *Channel) isSendPending() bool { func (ch *Channel) nextPacketMsg() PacketMsg { packet := PacketMsg{} packet.ChannelID = byte(ch.desc.ID) - maxSize := ch.maxPacketMsgPayloadSize + maxSize := ch.maxPacketMsgPayloadSize - ch.conn.emptyPacketMsgSize packet.Bytes = ch.sending[:cmn.MinInt(maxSize, len(ch.sending))] if len(ch.sending) <= maxSize { packet.EOF = byte(0x01) @@ -782,3 +780,25 @@ type PacketMsg struct { func (mp PacketMsg) String() string { return fmt.Sprintf("PacketMsg{%X:%X T:%X}", mp.ChannelID, mp.Bytes, mp.EOF) } + +// - Uvarint length of MustMarshalBinary(packet) = 1 or 2 bytes +// (as long as it's less than 16,384 bytes) +// - Prefix bytes = 4 bytes +// - ChannelID field key + byte = 2 bytes +// - EOF field key + byte = 2 bytes +// - Bytes field key = 1 bytes +// - Uvarint length of MustMarshalBinary(bytes) = 1 or 2 bytes +// - Struct terminator = 1 byte +// = up to 14 bytes overhead for the packet. + +func emptyPacketMsgSize() int { + emptyPacketMsgSize := len(cdc.MustMarshalBinary(PacketMsg{ + ChannelID: 0x01, + EOF: 1, + Bytes: make([]byte, 1), + })) + // -1 byte of data + // +1 byte because uvarint length of MustMarshalBinary(bytes) will be 2 bytes for big packets + // +1 byte because uvarint length of MustMarshalBinary(packet) will be 2 bytes for big packets + return emptyPacketMsgSize - 1 + 1 + 1 +} diff --git a/p2p/conn/connection_test.go b/p2p/conn/connection_test.go index ade8e8e9f..34b37ab8a 100644 --- a/p2p/conn/connection_test.go +++ b/p2p/conn/connection_test.go @@ -14,6 +14,8 @@ import ( "github.com/tendermint/tmlibs/log" ) +const maxPingPongPacketSize = 1024 // bytes + func createTestMConnection(conn net.Conn) *MConnection { onReceive := func(chID byte, msgBytes []byte) { } @@ -138,8 +140,7 @@ func TestMConnectionPongTimeoutResultsInError(t *testing.T) { go func() { // read ping var pkt PacketPing - const maxPacketPingSize = 1024 - _, err = cdc.UnmarshalBinaryReader(server, &pkt, maxPacketPingSize) + _, err = cdc.UnmarshalBinaryReader(server, &pkt, maxPingPongPacketSize) assert.Nil(t, err) serverGotPing <- struct{}{} }() @@ -186,7 +187,7 @@ func TestMConnectionMultiplePongsInTheBeginning(t *testing.T) { go func() { // read ping (one byte) var packet, err = Packet(nil), error(nil) - _, err = cdc.UnmarshalBinaryReader(server, &packet, 1024) + _, err = cdc.UnmarshalBinaryReader(server, &packet, maxPingPongPacketSize) require.Nil(t, err) serverGotPing <- struct{}{} // respond with pong @@ -229,15 +230,15 @@ func TestMConnectionMultiplePings(t *testing.T) { _, err = server.Write(cdc.MustMarshalBinary(PacketPing{})) require.Nil(t, err) var pkt PacketPong - _, err = cdc.UnmarshalBinaryReader(server, &pkt, 1024) + _, err = cdc.UnmarshalBinaryReader(server, &pkt, maxPingPongPacketSize) require.Nil(t, err) _, err = server.Write(cdc.MustMarshalBinary(PacketPing{})) require.Nil(t, err) - _, err = cdc.UnmarshalBinaryReader(server, &pkt, 1024) + _, err = cdc.UnmarshalBinaryReader(server, &pkt, maxPingPongPacketSize) require.Nil(t, err) _, err = server.Write(cdc.MustMarshalBinary(PacketPing{})) require.Nil(t, err) - _, err = cdc.UnmarshalBinaryReader(server, &pkt, 1024) + _, err = cdc.UnmarshalBinaryReader(server, &pkt, maxPingPongPacketSize) require.Nil(t, err) assert.True(t, mconn.IsRunning()) @@ -269,7 +270,7 @@ func TestMConnectionPingPongs(t *testing.T) { go func() { // read ping var pkt PacketPing - _, err = cdc.UnmarshalBinaryReader(server, &pkt, 1024) + _, err = cdc.UnmarshalBinaryReader(server, &pkt, maxPingPongPacketSize) require.Nil(t, err) serverGotPing <- struct{}{} // respond with pong @@ -279,7 +280,7 @@ func TestMConnectionPingPongs(t *testing.T) { time.Sleep(mconn.config.PingInterval) // read ping - _, err = cdc.UnmarshalBinaryReader(server, &pkt, 1024) + _, err = cdc.UnmarshalBinaryReader(server, &pkt, maxPingPongPacketSize) require.Nil(t, err) // respond with pong _, err = server.Write(cdc.MustMarshalBinary(PacketPong{})) @@ -422,19 +423,10 @@ func TestMConnectionReadErrorLongMessage(t *testing.T) { // send msg thats just right var err error var buf = new(bytes.Buffer) - // - Uvarint length of MustMarshalBinary(packet) = 1 or 2 bytes - // (as long as it's less than 16,384 bytes) - // - Prefix bytes = 4 bytes - // - ChannelID field key + byte = 2 bytes - // - EOF field key + byte = 2 bytes - // - Bytes field key = 1 bytes - // - Uvarint length of MustMarshalBinary(bytes) = 1 or 2 bytes - // - Struct terminator = 1 byte - // = up to 14 bytes overhead for the packet. var packet = PacketMsg{ ChannelID: 0x01, EOF: 1, - Bytes: make([]byte, mconnClient.config.MaxPacketMsgPayloadSize), + Bytes: make([]byte, mconnClient.config.MaxPacketMsgSize-emptyPacketMsgSize()), } _, err = cdc.MarshalBinaryWriter(buf, packet) assert.Nil(t, err) @@ -448,7 +440,7 @@ func TestMConnectionReadErrorLongMessage(t *testing.T) { packet = PacketMsg{ ChannelID: 0x01, EOF: 1, - Bytes: make([]byte, mconnClient.config.MaxPacketMsgPayloadSize+1), + Bytes: make([]byte, mconnClient.config.MaxPacketMsgSize+1), } _, err = cdc.MarshalBinaryWriter(buf, packet) assert.Nil(t, err) diff --git a/p2p/conn/secret_connection.go b/p2p/conn/secret_connection.go index 2a507f882..43f84f0bf 100644 --- a/p2p/conn/secret_connection.go +++ b/p2p/conn/secret_connection.go @@ -20,7 +20,7 @@ import ( "golang.org/x/crypto/nacl/secretbox" "golang.org/x/crypto/ripemd160" - "github.com/tendermint/go-crypto" + "github.com/tendermint/tendermint/crypto" cmn "github.com/tendermint/tmlibs/common" ) @@ -267,7 +267,11 @@ func genChallenge(loPubKey, hiPubKey *[32]byte) (challenge *[32]byte) { } func signChallenge(challenge *[32]byte, locPrivKey crypto.PrivKey) (signature crypto.Signature) { - signature = locPrivKey.Sign(challenge[:]) + signature, err := locPrivKey.Sign(challenge[:]) + // TODO(ismail): let signChallenge return an error instead + if err != nil { + panic(err) + } return } diff --git a/p2p/conn/secret_connection_test.go b/p2p/conn/secret_connection_test.go index 8dfc2bef0..7f862fecd 100644 --- a/p2p/conn/secret_connection_test.go +++ b/p2p/conn/secret_connection_test.go @@ -7,7 +7,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - crypto "github.com/tendermint/go-crypto" + crypto "github.com/tendermint/tendermint/crypto" cmn "github.com/tendermint/tmlibs/common" ) diff --git a/p2p/conn/wire.go b/p2p/conn/wire.go index 02d67f6fb..3182fde38 100644 --- a/p2p/conn/wire.go +++ b/p2p/conn/wire.go @@ -2,7 +2,7 @@ package conn import ( "github.com/tendermint/go-amino" - "github.com/tendermint/go-crypto" + "github.com/tendermint/tendermint/crypto" ) var cdc *amino.Codec = amino.NewCodec() diff --git a/p2p/key.go b/p2p/key.go index 73103ebd4..7e242bfc3 100644 --- a/p2p/key.go +++ b/p2p/key.go @@ -6,7 +6,7 @@ import ( "fmt" "io/ioutil" - crypto "github.com/tendermint/go-crypto" + crypto "github.com/tendermint/tendermint/crypto" cmn "github.com/tendermint/tmlibs/common" ) diff --git a/p2p/peer.go b/p2p/peer.go index da69fe74f..cf96354e6 100644 --- a/p2p/peer.go +++ b/p2p/peer.go @@ -6,7 +6,7 @@ import ( "sync/atomic" "time" - crypto "github.com/tendermint/go-crypto" + crypto "github.com/tendermint/tendermint/crypto" cmn "github.com/tendermint/tmlibs/common" "github.com/tendermint/tmlibs/log" diff --git a/p2p/peer_set_test.go b/p2p/peer_set_test.go index 1675812fe..32d312437 100644 --- a/p2p/peer_set_test.go +++ b/p2p/peer_set_test.go @@ -8,7 +8,7 @@ import ( "github.com/stretchr/testify/assert" - crypto "github.com/tendermint/go-crypto" + crypto "github.com/tendermint/tendermint/crypto" cmn "github.com/tendermint/tmlibs/common" ) diff --git a/p2p/peer_test.go b/p2p/peer_test.go index 3a477199d..73c0db825 100644 --- a/p2p/peer_test.go +++ b/p2p/peer_test.go @@ -9,7 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - crypto "github.com/tendermint/go-crypto" + crypto "github.com/tendermint/tendermint/crypto" cmn "github.com/tendermint/tmlibs/common" "github.com/tendermint/tmlibs/log" diff --git a/p2p/pex/addrbook.go b/p2p/pex/addrbook.go index dc51761fe..592269957 100644 --- a/p2p/pex/addrbook.go +++ b/p2p/pex/addrbook.go @@ -12,7 +12,7 @@ import ( "sync" "time" - crypto "github.com/tendermint/go-crypto" + crypto "github.com/tendermint/tendermint/crypto" "github.com/tendermint/tendermint/p2p" cmn "github.com/tendermint/tmlibs/common" ) diff --git a/p2p/pex/pex_reactor_test.go b/p2p/pex/pex_reactor_test.go index 645e93171..f4251e869 100644 --- a/p2p/pex/pex_reactor_test.go +++ b/p2p/pex/pex_reactor_test.go @@ -12,7 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - crypto "github.com/tendermint/go-crypto" + crypto "github.com/tendermint/tendermint/crypto" cmn "github.com/tendermint/tmlibs/common" "github.com/tendermint/tmlibs/log" diff --git a/p2p/switch.go b/p2p/switch.go index bf5f9747f..ae322b54f 100644 --- a/p2p/switch.go +++ b/p2p/switch.go @@ -100,7 +100,7 @@ func NewSwitch(cfg *config.P2PConfig, options ...SwitchOption) *Switch { mConfig.FlushThrottle = time.Duration(cfg.FlushThrottleTimeout) * time.Millisecond mConfig.SendRate = cfg.SendRate mConfig.RecvRate = cfg.RecvRate - mConfig.MaxPacketMsgPayloadSize = cfg.MaxPacketMsgPayloadSize + mConfig.MaxPacketMsgSize = cfg.MaxPacketMsgSize sw.mConfig = mConfig diff --git a/p2p/switch_test.go b/p2p/switch_test.go index 6157f45c6..afccfd585 100644 --- a/p2p/switch_test.go +++ b/p2p/switch_test.go @@ -11,7 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - crypto "github.com/tendermint/go-crypto" + crypto "github.com/tendermint/tendermint/crypto" "github.com/tendermint/tmlibs/log" "github.com/tendermint/tendermint/config" diff --git a/p2p/test_util.go b/p2p/test_util.go index 0d2ba6c5e..b0b801487 100644 --- a/p2p/test_util.go +++ b/p2p/test_util.go @@ -4,7 +4,7 @@ import ( "fmt" "net" - crypto "github.com/tendermint/go-crypto" + crypto "github.com/tendermint/tendermint/crypto" cmn "github.com/tendermint/tmlibs/common" "github.com/tendermint/tmlibs/log" diff --git a/p2p/wire.go b/p2p/wire.go index a90ac851c..b7ae41253 100644 --- a/p2p/wire.go +++ b/p2p/wire.go @@ -2,7 +2,7 @@ package p2p import ( "github.com/tendermint/go-amino" - "github.com/tendermint/go-crypto" + "github.com/tendermint/tendermint/crypto" ) var cdc = amino.NewCodec() diff --git a/privval/priv_validator.go b/privval/priv_validator.go index 2bb5ef323..9f02482ab 100644 --- a/privval/priv_validator.go +++ b/privval/priv_validator.go @@ -8,7 +8,7 @@ import ( "sync" "time" - "github.com/tendermint/go-crypto" + "github.com/tendermint/tendermint/crypto" "github.com/tendermint/tendermint/types" cmn "github.com/tendermint/tmlibs/common" ) @@ -222,7 +222,10 @@ func (pv *FilePV) signVote(chainID string, vote *types.Vote) error { } // It passed the checks. Sign the vote - sig := pv.PrivKey.Sign(signBytes) + sig, err := pv.PrivKey.Sign(signBytes) + if err != nil { + return err + } pv.saveSigned(height, round, step, signBytes, sig) vote.Signature = sig return nil @@ -258,7 +261,10 @@ func (pv *FilePV) signProposal(chainID string, proposal *types.Proposal) error { } // It passed the checks. Sign the proposal - sig := pv.PrivKey.Sign(signBytes) + sig, err := pv.PrivKey.Sign(signBytes) + if err != nil { + return err + } pv.saveSigned(height, round, step, signBytes, sig) proposal.Signature = sig return nil @@ -281,7 +287,11 @@ func (pv *FilePV) saveSigned(height int64, round int, step int8, func (pv *FilePV) SignHeartbeat(chainID string, heartbeat *types.Heartbeat) error { pv.mtx.Lock() defer pv.mtx.Unlock() - heartbeat.Signature = pv.PrivKey.Sign(heartbeat.SignBytes(chainID)) + sig, err:= pv.PrivKey.Sign(heartbeat.SignBytes(chainID)) + if err != nil { + return err + } + heartbeat.Signature = sig return nil } diff --git a/privval/priv_validator_test.go b/privval/priv_validator_test.go index c7212d594..4fc8f97fc 100644 --- a/privval/priv_validator_test.go +++ b/privval/priv_validator_test.go @@ -9,8 +9,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/tendermint/go-crypto" "github.com/tendermint/tendermint/types" + "github.com/tendermint/tendermint/crypto" cmn "github.com/tendermint/tmlibs/common" ) @@ -60,14 +60,14 @@ func TestUnmarshalValidator(t *testing.T) { serialized := fmt.Sprintf(`{ "address": "%s", "pub_key": { - "type": "AC26791624DE60", + "type": "tendermint/PubKeyEd25519", "value": "%s" }, - "last_height": 0, - "last_round": 0, + "last_height": "0", + "last_round": "0", "last_step": 0, "priv_key": { - "type": "954568A3288910", + "type": "tendermint/PrivKeyEd25519", "value": "%s" } }`, addr, pubB64, privB64) diff --git a/privval/socket.go b/privval/socket.go index 9f59a8152..d0be3ba4e 100644 --- a/privval/socket.go +++ b/privval/socket.go @@ -8,7 +8,7 @@ import ( "time" "github.com/tendermint/go-amino" - "github.com/tendermint/go-crypto" + "github.com/tendermint/tendermint/crypto" cmn "github.com/tendermint/tmlibs/common" "github.com/tendermint/tmlibs/log" diff --git a/privval/socket_test.go b/privval/socket_test.go index 197c2508e..fcf21e0c6 100644 --- a/privval/socket_test.go +++ b/privval/socket_test.go @@ -9,7 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/tendermint/go-crypto" + "github.com/tendermint/tendermint/crypto" cmn "github.com/tendermint/tmlibs/common" "github.com/tendermint/tmlibs/log" diff --git a/privval/wire.go b/privval/wire.go index 688910834..c42ba40d6 100644 --- a/privval/wire.go +++ b/privval/wire.go @@ -2,7 +2,7 @@ package privval import ( "github.com/tendermint/go-amino" - "github.com/tendermint/go-crypto" + "github.com/tendermint/tendermint/crypto" ) var cdc = amino.NewCodec() diff --git a/rpc/core/consensus.go b/rpc/core/consensus.go index dad64b6b6..c026cd91f 100644 --- a/rpc/core/consensus.go +++ b/rpc/core/consensus.go @@ -87,7 +87,7 @@ func Validators(heightPtr *int64) (*ctypes.ResultValidators, error) { // { // "address": "B5B3D40BE53982AD294EF99FF5A34C0C3E5A3244", // "pub_key": { -// "type": "AC26791624DE60", +// "type": "tendermint/PubKeyEd25519", // "value": "SBctdhRBcXtBgdI/8a/alTsUhGXqGs9k5ylV1u5iKHg=" // }, // "voting_power": 10, @@ -97,7 +97,7 @@ func Validators(heightPtr *int64) (*ctypes.ResultValidators, error) { // "proposer": { // "address": "B5B3D40BE53982AD294EF99FF5A34C0C3E5A3244", // "pub_key": { -// "type": "AC26791624DE60", +// "type": "tendermint/PubKeyEd25519", // "value": "SBctdhRBcXtBgdI/8a/alTsUhGXqGs9k5ylV1u5iKHg=" // }, // "voting_power": 10, @@ -133,7 +133,7 @@ func Validators(heightPtr *int64) (*ctypes.ResultValidators, error) { // { // "address": "B5B3D40BE53982AD294EF99FF5A34C0C3E5A3244", // "pub_key": { -// "type": "AC26791624DE60", +// "type": "tendermint/PubKeyEd25519", // "value": "SBctdhRBcXtBgdI/8a/alTsUhGXqGs9k5ylV1u5iKHg=" // }, // "voting_power": 10, @@ -143,7 +143,7 @@ func Validators(heightPtr *int64) (*ctypes.ResultValidators, error) { // "proposer": { // "address": "B5B3D40BE53982AD294EF99FF5A34C0C3E5A3244", // "pub_key": { -// "type": "AC26791624DE60", +// "type": "tendermint/PubKeyEd25519", // "value": "SBctdhRBcXtBgdI/8a/alTsUhGXqGs9k5ylV1u5iKHg=" // }, // "voting_power": 10, diff --git a/rpc/core/pipe.go b/rpc/core/pipe.go index 7a042362f..9fcb75e19 100644 --- a/rpc/core/pipe.go +++ b/rpc/core/pipe.go @@ -3,7 +3,7 @@ package core import ( "time" - crypto "github.com/tendermint/go-crypto" + crypto "github.com/tendermint/tendermint/crypto" "github.com/tendermint/tendermint/consensus" "github.com/tendermint/tendermint/p2p" "github.com/tendermint/tendermint/proxy" diff --git a/rpc/core/status.go b/rpc/core/status.go index 044c12899..c1f0e9f2a 100644 --- a/rpc/core/status.go +++ b/rpc/core/status.go @@ -55,7 +55,7 @@ import ( // "validator_info": { // "address": "5875562FF0FFDECC895C20E32FC14988952E99E7", // "pub_key": { -// "type": "AC26791624DE60", +// "type": "tendermint/PubKeyEd25519", // "value": "PpDJRUrLG2RgFqYYjawfn/AcAgacSXpLFrmfYYQnuzE=" // }, // "voting_power": 10 diff --git a/rpc/core/types/responses.go b/rpc/core/types/responses.go index 5b001d7d3..8c0053b7d 100644 --- a/rpc/core/types/responses.go +++ b/rpc/core/types/responses.go @@ -6,7 +6,7 @@ import ( "time" abci "github.com/tendermint/abci/types" - crypto "github.com/tendermint/go-crypto" + crypto "github.com/tendermint/tendermint/crypto" cmn "github.com/tendermint/tmlibs/common" "github.com/tendermint/tendermint/p2p" diff --git a/rpc/core/types/wire.go b/rpc/core/types/wire.go index 6648364b1..d3a31dc35 100644 --- a/rpc/core/types/wire.go +++ b/rpc/core/types/wire.go @@ -2,7 +2,7 @@ package core_types import ( "github.com/tendermint/go-amino" - "github.com/tendermint/go-crypto" + "github.com/tendermint/tendermint/crypto" "github.com/tendermint/tendermint/types" ) diff --git a/rpc/lib/client/args_test.go b/rpc/lib/client/args_test.go index 4442ac2bc..cb7a56bd5 100644 --- a/rpc/lib/client/args_test.go +++ b/rpc/lib/client/args_test.go @@ -26,7 +26,7 @@ func TestArgToJSON(t *testing.T) { }{ {[]byte("1234"), "0x31323334"}, {Tx("654"), "0x363534"}, - {Foo{7, "hello"}, `{"Bar":7,"Baz":"hello"}`}, + {Foo{7, "hello"}, `{"Bar":"7","Baz":"hello"}`}, } cdc := amino.NewCodec() diff --git a/rpc/lib/server/handlers_test.go b/rpc/lib/server/handlers_test.go index b1ea46754..af5665138 100644 --- a/rpc/lib/server/handlers_test.go +++ b/rpc/lib/server/handlers_test.go @@ -55,13 +55,13 @@ func TestRPCParams(t *testing.T) { {`{"jsonrpc": "2.0", "method": "y", "id": "0"}`, "Method not found"}, {`{"method": "c", "id": "0", "params": a}`, "invalid character"}, {`{"method": "c", "id": "0", "params": ["a"]}`, "got 1"}, - {`{"method": "c", "id": "0", "params": ["a", "b"]}`, "of type int"}, + {`{"method": "c", "id": "0", "params": ["a", "b"]}`, "invalid character"}, {`{"method": "c", "id": "0", "params": [1, 1]}`, "of type string"}, // good {`{"jsonrpc": "2.0", "method": "c", "id": "0", "params": null}`, ""}, {`{"method": "c", "id": "0", "params": {}}`, ""}, - {`{"method": "c", "id": "0", "params": ["a", 10]}`, ""}, + {`{"method": "c", "id": "0", "params": ["a", "10"]}`, ""}, } for i, tt := range tests { diff --git a/rpc/lib/server/parse_test.go b/rpc/lib/server/parse_test.go index f4323ef5d..d4a59c622 100644 --- a/rpc/lib/server/parse_test.go +++ b/rpc/lib/server/parse_test.go @@ -6,7 +6,7 @@ import ( "testing" "github.com/stretchr/testify/assert" - "github.com/tendermint/go-amino" + amino "github.com/tendermint/go-amino" cmn "github.com/tendermint/tmlibs/common" ) @@ -148,8 +148,8 @@ func TestParseRPC(t *testing.T) { fail bool }{ // should parse - {`[7, "flew"]`, 7, "flew", false}, - {`{"name": "john", "height": 22}`, 22, "john", false}, + {`["7", "flew"]`, 7, "flew", false}, + {`{"name": "john", "height": "22"}`, 22, "john", false}, // defaults {`{"name": "solo", "unused": "stuff"}`, 0, "solo", false}, // should fail - wrong types/length diff --git a/scripts/wire2amino.go b/scripts/wire2amino.go index a942ceaad..72f472dac 100644 --- a/scripts/wire2amino.go +++ b/scripts/wire2amino.go @@ -9,7 +9,7 @@ import ( "time" "github.com/tendermint/go-amino" - crypto "github.com/tendermint/go-crypto" + crypto "github.com/tendermint/tendermint/crypto" cmn "github.com/tendermint/tmlibs/common" "github.com/tendermint/tendermint/p2p" diff --git a/state/execution_test.go b/state/execution_test.go index b520b0c12..921bda59b 100644 --- a/state/execution_test.go +++ b/state/execution_test.go @@ -10,7 +10,7 @@ import ( "github.com/tendermint/abci/example/kvstore" abci "github.com/tendermint/abci/types" - crypto "github.com/tendermint/go-crypto" + crypto "github.com/tendermint/tendermint/crypto" cmn "github.com/tendermint/tmlibs/common" dbm "github.com/tendermint/tmlibs/db" "github.com/tendermint/tmlibs/log" diff --git a/state/state_test.go b/state/state_test.go index 464456ca5..67de68487 100644 --- a/state/state_test.go +++ b/state/state_test.go @@ -8,7 +8,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" abci "github.com/tendermint/abci/types" - crypto "github.com/tendermint/go-crypto" + crypto "github.com/tendermint/tendermint/crypto" cmn "github.com/tendermint/tmlibs/common" dbm "github.com/tendermint/tmlibs/db" diff --git a/state/wire.go b/state/wire.go index 3e8b544d9..af743c7b8 100644 --- a/state/wire.go +++ b/state/wire.go @@ -2,7 +2,7 @@ package state import ( "github.com/tendermint/go-amino" - "github.com/tendermint/go-crypto" + "github.com/tendermint/tendermint/crypto" ) var cdc = amino.NewCodec() diff --git a/test/p2p/atomic_broadcast/test.sh b/test/p2p/atomic_broadcast/test.sh index 4e3cc1d86..f066707d3 100644 --- a/test/p2p/atomic_broadcast/test.sh +++ b/test/p2p/atomic_broadcast/test.sh @@ -26,11 +26,11 @@ for i in $(seq 1 "$N"); do echo "" # we need to wait another block to get the new app_hash - h1=$(curl -s "$addr/status" | jq .result.sync_info.latest_block_height) + h1=$(curl -s "$addr/status" | jq .result.sync_info.latest_block_height | jq fromjson) h2=$h1 while [ "$h2" == "$h1" ]; do sleep 1 - h2=$(curl -s "$addr/status" | jq .result.sync_info.latest_block_height) + h2=$(curl -s "$addr/status" | jq .result.sync_info.latest_block_height | jq fromjson) done # wait for all other peers to get to this height @@ -39,10 +39,10 @@ for i in $(seq 1 "$N"); do if [[ "$i" != "$j" ]]; then addrJ=$(test/p2p/ip.sh "$j"):26657 - h=$(curl -s "$addrJ/status" | jq .result.sync_info.latest_block_height) + h=$(curl -s "$addrJ/status" | jq .result.sync_info.latest_block_height | jq fromjson) while [ "$h" -lt "$minHeight" ]; do sleep 1 - h=$(curl -s "$addrJ/status" | jq .result.sync_info.latest_block_height) + h=$(curl -s "$addrJ/status" | jq .result.sync_info.latest_block_height | jq fromjson) done fi done diff --git a/test/p2p/basic/test.sh b/test/p2p/basic/test.sh index 6b356db2d..caf665122 100755 --- a/test/p2p/basic/test.sh +++ b/test/p2p/basic/test.sh @@ -54,12 +54,12 @@ for i in `seq 1 $N`; do done # - assert block height is greater than 1 - BLOCK_HEIGHT=`curl -s $addr/status | jq .result.sync_info.latest_block_height` + BLOCK_HEIGHT=`curl -s $addr/status | jq .result.sync_info.latest_block_height | jq fromjson` COUNT=0 while [ "$BLOCK_HEIGHT" -le 1 ]; do echo "Waiting for node $i to commit a block ..." sleep 1 - BLOCK_HEIGHT=`curl -s $addr/status | jq .result.sync_info.latest_block_height` + BLOCK_HEIGHT=`curl -s $addr/status | jq .result.sync_info.latest_block_height | jq fromjson` COUNT=$((COUNT+1)) if [ "$COUNT" -gt "$MAX_SLEEP" ]; then echo "Waited too long for node $i to commit a block" diff --git a/test/p2p/data/mach1/core/config/genesis.json b/test/p2p/data/mach1/core/config/genesis.json index 19577db00..515c10714 100644 --- a/test/p2p/data/mach1/core/config/genesis.json +++ b/test/p2p/data/mach1/core/config/genesis.json @@ -4,34 +4,34 @@ "validators": [ { "pub_key": { - "type": "AC26791624DE60", + "type": "tendermint/PubKeyEd25519", "value": "vokz3/FgDAJuNHGPF4Wkzeq5DDVpizlOOLaUeukd4RY=" }, - "power": 1, + "power": "1", "name": "mach1" }, { "pub_key": { - "type": "AC26791624DE60", + "type": "tendermint/PubKeyEd25519", "value": "bcU0RlMjEmWH0qKpO1nWibcXBzsd6WiiWm7xPVlTGK0=" }, - "power": 1, + "power": "1", "name": "mach2" }, { "pub_key": { - "type": "AC26791624DE60", + "type": "tendermint/PubKeyEd25519", "value": "rmesaX0TWqC0YB6lfqqz/r9Lqk8inEWlmMKYWxL80aE=" }, - "power": 1, + "power": "1", "name": "mach3" }, { "pub_key": { - "type": "AC26791624DE60", + "type": "tendermint/PubKeyEd25519", "value": "nryPWM7UtG3NWrirpZHdJTzXy1A3Jz/aMrwLZGHE79k=" }, - "power": 1, + "power": "1", "name": "mach4" } ], diff --git a/test/p2p/data/mach1/core/config/node_key.json b/test/p2p/data/mach1/core/config/node_key.json index c6d65008f..4fa960850 100644 --- a/test/p2p/data/mach1/core/config/node_key.json +++ b/test/p2p/data/mach1/core/config/node_key.json @@ -1,6 +1,6 @@ { "priv_key": { - "type": "954568A3288910", + "type": "tendermint/PrivKeyEd25519", "value": "BpYtFp8xSrudBa5aBLRuSPD72PGDAUm0dJORDL3Kd5YJbluUzRefVFrjwoHZv1yeDj2P9xkEi2L3hJCUz/qFkQ==" } } diff --git a/test/p2p/data/mach1/core/config/priv_validator.json b/test/p2p/data/mach1/core/config/priv_validator.json index 08c7c503b..ea2a01f5c 100644 --- a/test/p2p/data/mach1/core/config/priv_validator.json +++ b/test/p2p/data/mach1/core/config/priv_validator.json @@ -1,14 +1,14 @@ { - "address": "7E9D1FB08EDBAFCF116638D4C8FAFAEE2ABE1AAA", + "address": "AE47BBD4B3ACD80BFE17F6E0C66C5B8492A81AE4", "pub_key": { - "type": "AC26791624DE60", + "type": "tendermint/PubKeyEd25519", "value": "vokz3/FgDAJuNHGPF4Wkzeq5DDVpizlOOLaUeukd4RY=" }, - "last_height": 0, - "last_round": 0, + "last_height": "0", + "last_round": "0", "last_step": 0, "priv_key": { - "type": "954568A3288910", + "type": "tendermint/PrivKeyEd25519", "value": "VHqgfHqM4WxcsqQMbCbRWwoylgQQqfHqblC2NvGrOJq+iTPf8WAMAm40cY8XhaTN6rkMNWmLOU44tpR66R3hFg==" } } diff --git a/test/p2p/data/mach2/core/config/genesis.json b/test/p2p/data/mach2/core/config/genesis.json index 19577db00..515c10714 100644 --- a/test/p2p/data/mach2/core/config/genesis.json +++ b/test/p2p/data/mach2/core/config/genesis.json @@ -4,34 +4,34 @@ "validators": [ { "pub_key": { - "type": "AC26791624DE60", + "type": "tendermint/PubKeyEd25519", "value": "vokz3/FgDAJuNHGPF4Wkzeq5DDVpizlOOLaUeukd4RY=" }, - "power": 1, + "power": "1", "name": "mach1" }, { "pub_key": { - "type": "AC26791624DE60", + "type": "tendermint/PubKeyEd25519", "value": "bcU0RlMjEmWH0qKpO1nWibcXBzsd6WiiWm7xPVlTGK0=" }, - "power": 1, + "power": "1", "name": "mach2" }, { "pub_key": { - "type": "AC26791624DE60", + "type": "tendermint/PubKeyEd25519", "value": "rmesaX0TWqC0YB6lfqqz/r9Lqk8inEWlmMKYWxL80aE=" }, - "power": 1, + "power": "1", "name": "mach3" }, { "pub_key": { - "type": "AC26791624DE60", + "type": "tendermint/PubKeyEd25519", "value": "nryPWM7UtG3NWrirpZHdJTzXy1A3Jz/aMrwLZGHE79k=" }, - "power": 1, + "power": "1", "name": "mach4" } ], diff --git a/test/p2p/data/mach2/core/config/node_key.json b/test/p2p/data/mach2/core/config/node_key.json index 146a1328d..6eb151106 100644 --- a/test/p2p/data/mach2/core/config/node_key.json +++ b/test/p2p/data/mach2/core/config/node_key.json @@ -1,6 +1,6 @@ { "priv_key": { - "type": "954568A3288910", + "type": "tendermint/PrivKeyEd25519", "value": "uM6LDVE4wQIIUmq9rc6RxzX8zEGG4G4Jcuw15klzQopF68YfJM4bkbPSavurEcJ4nvBMusKBg2GcARFrZqnFKA==" } } diff --git a/test/p2p/data/mach2/core/config/priv_validator.json b/test/p2p/data/mach2/core/config/priv_validator.json index 8e813dff4..6e0cd7f8f 100644 --- a/test/p2p/data/mach2/core/config/priv_validator.json +++ b/test/p2p/data/mach2/core/config/priv_validator.json @@ -1,14 +1,14 @@ { - "address": "8893D14FE09F1157E39CD34B98036048D51B4985", + "address": "5D61EE46CCE91F579086522D7FD8CEC3F854E946", "pub_key": { - "type": "AC26791624DE60", + "type": "tendermint/PubKeyEd25519", "value": "bcU0RlMjEmWH0qKpO1nWibcXBzsd6WiiWm7xPVlTGK0=" }, - "last_height": 0, - "last_round": 0, + "last_height": "0", + "last_round": "0", "last_step": 0, "priv_key": { - "type": "954568A3288910", + "type": "tendermint/PrivKeyEd25519", "value": "0EeInmBQL8MSnQq38zSxg47Z7R7Nmcu5a3GtWr9agUNtxTRGUyMSZYfSoqk7WdaJtxcHOx3paKJabvE9WVMYrQ==" } } diff --git a/test/p2p/data/mach3/core/config/genesis.json b/test/p2p/data/mach3/core/config/genesis.json index 19577db00..515c10714 100644 --- a/test/p2p/data/mach3/core/config/genesis.json +++ b/test/p2p/data/mach3/core/config/genesis.json @@ -4,34 +4,34 @@ "validators": [ { "pub_key": { - "type": "AC26791624DE60", + "type": "tendermint/PubKeyEd25519", "value": "vokz3/FgDAJuNHGPF4Wkzeq5DDVpizlOOLaUeukd4RY=" }, - "power": 1, + "power": "1", "name": "mach1" }, { "pub_key": { - "type": "AC26791624DE60", + "type": "tendermint/PubKeyEd25519", "value": "bcU0RlMjEmWH0qKpO1nWibcXBzsd6WiiWm7xPVlTGK0=" }, - "power": 1, + "power": "1", "name": "mach2" }, { "pub_key": { - "type": "AC26791624DE60", + "type": "tendermint/PubKeyEd25519", "value": "rmesaX0TWqC0YB6lfqqz/r9Lqk8inEWlmMKYWxL80aE=" }, - "power": 1, + "power": "1", "name": "mach3" }, { "pub_key": { - "type": "AC26791624DE60", + "type": "tendermint/PubKeyEd25519", "value": "nryPWM7UtG3NWrirpZHdJTzXy1A3Jz/aMrwLZGHE79k=" }, - "power": 1, + "power": "1", "name": "mach4" } ], diff --git a/test/p2p/data/mach3/core/config/node_key.json b/test/p2p/data/mach3/core/config/node_key.json index 82689b8e0..0885bcf9c 100644 --- a/test/p2p/data/mach3/core/config/node_key.json +++ b/test/p2p/data/mach3/core/config/node_key.json @@ -1,6 +1,6 @@ { "priv_key": { - "type": "954568A3288910", + "type": "tendermint/PrivKeyEd25519", "value": "kT3orG0YkipT9rAZbvAjtGk/7Pu1ZeCE8LSUF2jz2uiSs1rdlUVi/gccRlvCRLKvrtSicOyEkmk0FHPOGS3mgg==" } } diff --git a/test/p2p/data/mach3/core/config/priv_validator.json b/test/p2p/data/mach3/core/config/priv_validator.json index 84c98b98f..ec68ca7bb 100644 --- a/test/p2p/data/mach3/core/config/priv_validator.json +++ b/test/p2p/data/mach3/core/config/priv_validator.json @@ -1,14 +1,14 @@ { - "address": "7C747D7E002932B3864E3FBE9AC04287043F66A0", + "address": "705F9DA2CC7D7AF5F4519455ED99622E40E439A1", "pub_key": { - "type": "AC26791624DE60", + "type": "tendermint/PubKeyEd25519", "value": "rmesaX0TWqC0YB6lfqqz/r9Lqk8inEWlmMKYWxL80aE=" }, - "last_height": 0, - "last_round": 0, + "last_height": "0", + "last_round": "0", "last_step": 0, "priv_key": { - "type": "954568A3288910", + "type": "tendermint/PrivKeyEd25519", "value": "waTkfzSfxfVW9Kmie6d2uUQkwxK6ps9u5EuGc0jXw/KuZ6xpfRNaoLRgHqV+qrP+v0uqTyKcRaWYwphbEvzRoQ==" } } diff --git a/test/p2p/data/mach4/core/config/genesis.json b/test/p2p/data/mach4/core/config/genesis.json index 19577db00..515c10714 100644 --- a/test/p2p/data/mach4/core/config/genesis.json +++ b/test/p2p/data/mach4/core/config/genesis.json @@ -4,34 +4,34 @@ "validators": [ { "pub_key": { - "type": "AC26791624DE60", + "type": "tendermint/PubKeyEd25519", "value": "vokz3/FgDAJuNHGPF4Wkzeq5DDVpizlOOLaUeukd4RY=" }, - "power": 1, + "power": "1", "name": "mach1" }, { "pub_key": { - "type": "AC26791624DE60", + "type": "tendermint/PubKeyEd25519", "value": "bcU0RlMjEmWH0qKpO1nWibcXBzsd6WiiWm7xPVlTGK0=" }, - "power": 1, + "power": "1", "name": "mach2" }, { "pub_key": { - "type": "AC26791624DE60", + "type": "tendermint/PubKeyEd25519", "value": "rmesaX0TWqC0YB6lfqqz/r9Lqk8inEWlmMKYWxL80aE=" }, - "power": 1, + "power": "1", "name": "mach3" }, { "pub_key": { - "type": "AC26791624DE60", + "type": "tendermint/PubKeyEd25519", "value": "nryPWM7UtG3NWrirpZHdJTzXy1A3Jz/aMrwLZGHE79k=" }, - "power": 1, + "power": "1", "name": "mach4" } ], diff --git a/test/p2p/data/mach4/core/config/node_key.json b/test/p2p/data/mach4/core/config/node_key.json index a0c8d3917..d6a5d79c2 100644 --- a/test/p2p/data/mach4/core/config/node_key.json +++ b/test/p2p/data/mach4/core/config/node_key.json @@ -1,6 +1,6 @@ { "priv_key": { - "type": "954568A3288910", + "type": "tendermint/PrivKeyEd25519", "value": "QIIm8/QEEawiJi3Zozv+J9b+1CufCEkGs3lxGMlRy4L4FVIXCoXJTwYIrotZtwoMqLYEqQV1hbKKJmFA3GFelw==" } } diff --git a/test/p2p/data/mach4/core/config/priv_validator.json b/test/p2p/data/mach4/core/config/priv_validator.json index 4f88045b5..468550ea8 100644 --- a/test/p2p/data/mach4/core/config/priv_validator.json +++ b/test/p2p/data/mach4/core/config/priv_validator.json @@ -1,14 +1,14 @@ { - "address": "CEBEFE3CA1363D425643EF63FC179E77A50A1E9A", + "address": "D1054266EC9EEA511ED9A76DEFD520BBE1B5E850", "pub_key": { - "type": "AC26791624DE60", + "type": "tendermint/PubKeyEd25519", "value": "nryPWM7UtG3NWrirpZHdJTzXy1A3Jz/aMrwLZGHE79k=" }, - "last_height": 0, - "last_round": 0, + "last_height": "0", + "last_round": "0", "last_step": 0, "priv_key": { - "type": "954568A3288910", + "type": "tendermint/PrivKeyEd25519", "value": "xMw+0o8CDC29qYvNvwjDztNwRw508l6TjV0pXo49KwyevI9YztS0bc1auKulkd0lPNfLUDcnP9oyvAtkYcTv2Q==" } } diff --git a/test/p2p/fast_sync/check_peer.sh b/test/p2p/fast_sync/check_peer.sh index e69f977f7..d5d3fc2b5 100644 --- a/test/p2p/fast_sync/check_peer.sh +++ b/test/p2p/fast_sync/check_peer.sh @@ -15,7 +15,7 @@ peerID=$(( $(($ID % 4)) + 1 )) # 1->2 ... 3->4 ... 4->1 peer_addr=$(test/p2p/ip.sh $peerID):26657 # get another peer's height -h1=`curl -s $peer_addr/status | jq .result.sync_info.latest_block_height` +h1=`curl -s $peer_addr/status | jq .result.sync_info.latest_block_height | jq fromjson` # get another peer's state root1=`curl -s $peer_addr/status | jq .result.sync_info.latest_app_hash` @@ -29,7 +29,7 @@ set +o pipefail h2="0" while [[ "$h2" -lt "$(($h1+3))" ]]; do sleep 1 - h2=`curl -s $addr/status | jq .result.sync_info.latest_block_height` + h2=`curl -s $addr/status | jq .result.sync_info.latest_block_height | jq fromjson` echo "... $h2" done diff --git a/types/block_test.go b/types/block_test.go index 3c2942cd5..1132a6f5f 100644 --- a/types/block_test.go +++ b/types/block_test.go @@ -6,7 +6,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - crypto "github.com/tendermint/go-crypto" + crypto "github.com/tendermint/tendermint/crypto" cmn "github.com/tendermint/tmlibs/common" ) diff --git a/types/canonical_json.go b/types/canonical_json.go index 95ade9c67..258f7714b 100644 --- a/types/canonical_json.go +++ b/types/canonical_json.go @@ -3,14 +3,13 @@ package types import ( "time" - "github.com/tendermint/go-amino" cmn "github.com/tendermint/tmlibs/common" ) // Canonical json is amino's json for structs with fields in alphabetical order // TimeFormat is used for generating the sigs -const TimeFormat = amino.RFC3339Millis +const TimeFormat = "2006-01-02T15:04:05.000Z" type CanonicalJSONBlockID struct { Hash cmn.HexBytes `json:"hash,omitempty"` diff --git a/types/evidence.go b/types/evidence.go index 10907869e..4d8b59272 100644 --- a/types/evidence.go +++ b/types/evidence.go @@ -5,7 +5,7 @@ import ( "fmt" "github.com/tendermint/go-amino" - "github.com/tendermint/go-crypto" + "github.com/tendermint/tendermint/crypto" "github.com/tendermint/tmlibs/merkle" ) diff --git a/types/genesis.go b/types/genesis.go index aee8e0767..099bb499c 100644 --- a/types/genesis.go +++ b/types/genesis.go @@ -5,7 +5,7 @@ import ( "io/ioutil" "time" - "github.com/tendermint/go-crypto" + "github.com/tendermint/tendermint/crypto" cmn "github.com/tendermint/tmlibs/common" ) diff --git a/types/genesis_test.go b/types/genesis_test.go index bed4b90f5..24398a9a5 100644 --- a/types/genesis_test.go +++ b/types/genesis_test.go @@ -4,7 +4,7 @@ import ( "testing" "github.com/stretchr/testify/assert" - "github.com/tendermint/go-crypto" + "github.com/tendermint/tendermint/crypto" ) func TestGenesisBad(t *testing.T) { @@ -18,7 +18,7 @@ func TestGenesisBad(t *testing.T) { []byte(`{"chain_id":"mychain","validators":[{}]}`), // missing validators []byte(`{"chain_id":"mychain","validators":null}`), // missing validators []byte(`{"chain_id":"mychain"}`), // missing validators - []byte(`{"validators":[{"pub_key":{"type":"AC26791624DE60","value":"AT/+aaL1eB0477Mud9JMm8Sh8BIvOYlPGC9KkIUmFaE="},"power":10,"name":""}]}`), // missing chain_id + []byte(`{"validators":[{"pub_key":{"type":"tendermint/PubKeyEd25519","value":"AT/+aaL1eB0477Mud9JMm8Sh8BIvOYlPGC9KkIUmFaE="},"power":"10","name":""}]}`), // missing chain_id } for _, testCase := range testCases { @@ -29,7 +29,7 @@ func TestGenesisBad(t *testing.T) { func TestGenesisGood(t *testing.T) { // test a good one by raw json - genDocBytes := []byte(`{"genesis_time":"0001-01-01T00:00:00Z","chain_id":"test-chain-QDKdJr","consensus_params":null,"validators":[{"pub_key":{"type":"AC26791624DE60","value":"AT/+aaL1eB0477Mud9JMm8Sh8BIvOYlPGC9KkIUmFaE="},"power":10,"name":""}],"app_hash":"","app_state":{"account_owner": "Bob"}}`) + genDocBytes := []byte(`{"genesis_time":"0001-01-01T00:00:00Z","chain_id":"test-chain-QDKdJr","consensus_params":null,"validators":[{"pub_key":{"type":"tendermint/PubKeyEd25519","value":"AT/+aaL1eB0477Mud9JMm8Sh8BIvOYlPGC9KkIUmFaE="},"power":"10","name":""}],"app_hash":"","app_state":{"account_owner": "Bob"}}`) _, err := GenesisDocFromJSON(genDocBytes) assert.NoError(t, err, "expected no error for good genDoc json") diff --git a/types/heartbeat.go b/types/heartbeat.go index 097dd22db..fcf545f2c 100644 --- a/types/heartbeat.go +++ b/types/heartbeat.go @@ -3,7 +3,7 @@ package types import ( "fmt" - "github.com/tendermint/go-crypto" + "github.com/tendermint/tendermint/crypto" cmn "github.com/tendermint/tmlibs/common" ) diff --git a/types/heartbeat_test.go b/types/heartbeat_test.go index 3c4536028..174c3ba97 100644 --- a/types/heartbeat_test.go +++ b/types/heartbeat_test.go @@ -5,7 +5,7 @@ import ( "github.com/stretchr/testify/require" - "github.com/tendermint/go-crypto" + "github.com/tendermint/tendermint/crypto" ) func TestHeartbeatCopy(t *testing.T) { @@ -28,7 +28,9 @@ func TestHeartbeatString(t *testing.T) { require.Equal(t, hb.String(), "Heartbeat{1:000000000000 11/02 (0) }") var key crypto.PrivKeyEd25519 - hb.Signature = key.Sign([]byte("Tendermint")) + sig, err := key.Sign([]byte("Tendermint")) + require.NoError(t, err) + hb.Signature = sig require.Equal(t, hb.String(), "Heartbeat{1:000000000000 11/02 (0) /FF41E371B9BF.../}") } @@ -37,11 +39,11 @@ func TestHeartbeatWriteSignBytes(t *testing.T) { hb := &Heartbeat{ValidatorIndex: 1, Height: 10, Round: 1} bz := hb.SignBytes("0xdeadbeef") // XXX HMMMMMMM - require.Equal(t, string(bz), `{"@chain_id":"0xdeadbeef","@type":"heartbeat","height":10,"round":1,"sequence":0,"validator_address":"","validator_index":1}`) + require.Equal(t, string(bz), `{"@chain_id":"0xdeadbeef","@type":"heartbeat","height":"10","round":"1","sequence":"0","validator_address":"","validator_index":"1"}`) plainHb := &Heartbeat{} bz = plainHb.SignBytes("0xdeadbeef") - require.Equal(t, string(bz), `{"@chain_id":"0xdeadbeef","@type":"heartbeat","height":0,"round":0,"sequence":0,"validator_address":"","validator_index":0}`) + require.Equal(t, string(bz), `{"@chain_id":"0xdeadbeef","@type":"heartbeat","height":"0","round":"0","sequence":"0","validator_address":"","validator_index":"0"}`) require.Panics(t, func() { var nilHb *Heartbeat diff --git a/types/priv_validator.go b/types/priv_validator.go index 8759d3f99..85db65a41 100644 --- a/types/priv_validator.go +++ b/types/priv_validator.go @@ -4,7 +4,7 @@ import ( "bytes" "fmt" - "github.com/tendermint/go-crypto" + "github.com/tendermint/tendermint/crypto" ) // PrivValidator defines the functionality of a local Tendermint validator @@ -63,7 +63,10 @@ func (pv *MockPV) GetPubKey() crypto.PubKey { // Implements PrivValidator. func (pv *MockPV) SignVote(chainID string, vote *Vote) error { signBytes := vote.SignBytes(chainID) - sig := pv.privKey.Sign(signBytes) + sig, err := pv.privKey.Sign(signBytes) + if err != nil { + return err + } vote.Signature = sig return nil } @@ -71,14 +74,20 @@ func (pv *MockPV) SignVote(chainID string, vote *Vote) error { // Implements PrivValidator. func (pv *MockPV) SignProposal(chainID string, proposal *Proposal) error { signBytes := proposal.SignBytes(chainID) - sig := pv.privKey.Sign(signBytes) + sig, err := pv.privKey.Sign(signBytes) + if err != nil { + return err + } proposal.Signature = sig return nil } // signHeartbeat signs the heartbeat without any checking. func (pv *MockPV) SignHeartbeat(chainID string, heartbeat *Heartbeat) error { - sig := pv.privKey.Sign(heartbeat.SignBytes(chainID)) + sig, err := pv.privKey.Sign(heartbeat.SignBytes(chainID)) + if err != nil { + return err + } heartbeat.Signature = sig return nil } diff --git a/types/proposal.go b/types/proposal.go index 95008897b..52ce8756e 100644 --- a/types/proposal.go +++ b/types/proposal.go @@ -5,7 +5,7 @@ import ( "fmt" "time" - "github.com/tendermint/go-crypto" + "github.com/tendermint/tendermint/crypto" ) var ( diff --git a/types/proposal_test.go b/types/proposal_test.go index 43fb7c209..8aef870fc 100644 --- a/types/proposal_test.go +++ b/types/proposal_test.go @@ -27,7 +27,11 @@ func TestProposalSignable(t *testing.T) { signBytes := testProposal.SignBytes("test_chain_id") signStr := string(signBytes) - expected := `{"@chain_id":"test_chain_id","@type":"proposal","block_parts_header":{"hash":"626C6F636B7061727473","total":111},"height":12345,"pol_block_id":{},"pol_round":-1,"round":23456,"timestamp":"2018-02-11T07:09:22.765Z"}` + expected := `{"@chain_id":"test_chain_id","@type":"proposal","block_parts_header":{"hash":"626C6F636B7061727473","total":"111"},"height":"12345","pol_block_id":{},"pol_round":"-1","round":"23456","timestamp":"2018-02-11T07:09:22.765Z"}` + if signStr != expected { + t.Errorf("Got unexpected sign string for Proposal. Expected:\n%v\nGot:\n%v", expected, signStr) + } + if signStr != expected { t.Errorf("Got unexpected sign string for Proposal. Expected:\n%v\nGot:\n%v", expected, signStr) } diff --git a/types/protobuf.go b/types/protobuf.go index eb684ae7d..5155b4b81 100644 --- a/types/protobuf.go +++ b/types/protobuf.go @@ -7,7 +7,7 @@ import ( "time" abci "github.com/tendermint/abci/types" - crypto "github.com/tendermint/go-crypto" + crypto "github.com/tendermint/tendermint/crypto" ) //------------------------------------------------------- diff --git a/types/protobuf_test.go b/types/protobuf_test.go index 9f3b31873..da67e1c30 100644 --- a/types/protobuf_test.go +++ b/types/protobuf_test.go @@ -5,7 +5,7 @@ import ( "github.com/stretchr/testify/assert" abci "github.com/tendermint/abci/types" - crypto "github.com/tendermint/go-crypto" + crypto "github.com/tendermint/tendermint/crypto" ) func TestABCIPubKey(t *testing.T) { diff --git a/types/validator.go b/types/validator.go index 46dc61d07..bea975a4f 100644 --- a/types/validator.go +++ b/types/validator.go @@ -4,7 +4,7 @@ import ( "bytes" "fmt" - "github.com/tendermint/go-crypto" + "github.com/tendermint/tendermint/crypto" cmn "github.com/tendermint/tmlibs/common" ) diff --git a/types/validator_set_test.go b/types/validator_set_test.go index 8db53a533..c78a36063 100644 --- a/types/validator_set_test.go +++ b/types/validator_set_test.go @@ -10,7 +10,7 @@ import ( "github.com/stretchr/testify/assert" - crypto "github.com/tendermint/go-crypto" + crypto "github.com/tendermint/tendermint/crypto" cmn "github.com/tendermint/tmlibs/common" ) @@ -331,7 +331,9 @@ func TestValidatorSetVerifyCommit(t *testing.T) { Type: VoteTypePrecommit, BlockID: blockID, } - vote.Signature = privKey.Sign(vote.SignBytes(chainID)) + sig, err := privKey.Sign(vote.SignBytes(chainID)) + assert.NoError(t, err) + vote.Signature = sig commit := &Commit{ BlockID: blockID, Precommits: []*Vote{vote}, @@ -365,6 +367,6 @@ func TestValidatorSetVerifyCommit(t *testing.T) { } // test a good one - err := vset.VerifyCommit(chainID, blockID, height, commit) + err = vset.VerifyCommit(chainID, blockID, height, commit) assert.Nil(t, err) } diff --git a/types/vote.go b/types/vote.go index e4ead612a..1e7b263b6 100644 --- a/types/vote.go +++ b/types/vote.go @@ -6,7 +6,7 @@ import ( "fmt" "time" - crypto "github.com/tendermint/go-crypto" + crypto "github.com/tendermint/tendermint/crypto" cmn "github.com/tendermint/tmlibs/common" ) diff --git a/types/vote_set_test.go b/types/vote_set_test.go index d424667b1..9efef41ba 100644 --- a/types/vote_set_test.go +++ b/types/vote_set_test.go @@ -5,7 +5,7 @@ import ( "testing" "time" - crypto "github.com/tendermint/go-crypto" + crypto "github.com/tendermint/tendermint/crypto" cmn "github.com/tendermint/tmlibs/common" tst "github.com/tendermint/tmlibs/test" ) diff --git a/types/vote_test.go b/types/vote_test.go index 263d2c351..cbb22aaae 100644 --- a/types/vote_test.go +++ b/types/vote_test.go @@ -43,7 +43,7 @@ func TestVoteSignable(t *testing.T) { signBytes := vote.SignBytes("test_chain_id") signStr := string(signBytes) - expected := `{"@chain_id":"test_chain_id","@type":"vote","block_id":{"hash":"68617368","parts":{"hash":"70617274735F68617368","total":1000000}},"height":12345,"round":2,"timestamp":"2017-12-25T03:00:01.234Z","type":2}` + expected := `{"@chain_id":"test_chain_id","@type":"vote","block_id":{"hash":"68617368","parts":{"hash":"70617274735F68617368","total":"1000000"}},"height":"12345","round":"2","timestamp":"2017-12-25T03:00:01.234Z","type":2}` if signStr != expected { // NOTE: when this fails, you probably want to fix up consensus/replay_test too t.Errorf("Got unexpected sign string for Vote. Expected:\n%v\nGot:\n%v", expected, signStr) diff --git a/types/wire.go b/types/wire.go index bd5c4497d..6342d7eba 100644 --- a/types/wire.go +++ b/types/wire.go @@ -2,7 +2,7 @@ package types import ( "github.com/tendermint/go-amino" - "github.com/tendermint/go-crypto" + "github.com/tendermint/tendermint/crypto" ) var cdc = amino.NewCodec()