From ec710395b79cf0d96a60a5801f11c9204c701f48 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Sun, 1 Jul 2018 01:40:03 -0400 Subject: [PATCH] RIPEMD160 -> SHA256 --- Gopkg.lock | 2 +- docs/spec/blockchain/encoding.md | 16 ++++++++++++---- types/block.go | 6 +++--- types/evidence.go | 5 +++-- types/params.go | 2 +- types/part_set.go | 7 +++---- types/results.go | 4 +++- types/tx.go | 12 ++++++------ types/validator_set.go | 2 +- 9 files changed, 33 insertions(+), 23 deletions(-) diff --git a/Gopkg.lock b/Gopkg.lock index 6e1c41493..17b74d74b 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -286,7 +286,7 @@ "leveldb/table", "leveldb/util" ] - revision = "0d5a0ceb10cf9ab89fdd744cc8c50a83134f6697" + revision = "e2150783cd35f5b607daca48afd8c57ec54cc995" [[projects]] branch = "master" diff --git a/docs/spec/blockchain/encoding.md b/docs/spec/blockchain/encoding.md index df056ab2b..16902d099 100644 --- a/docs/spec/blockchain/encoding.md +++ b/docs/spec/blockchain/encoding.md @@ -151,7 +151,15 @@ func MakeParts(obj interface{}, partSize int) []Part Simple Merkle trees are used in numerous places in Tendermint to compute a cryptographic digest of a data structure. -RIPEMD160 is always used as the hashing function. +Tendermint always uses the `TMHASH` hash function, which is the first 20-bytes +of the SHA256: + +``` +func TMHASH(bz []byte) []byte { + shasum := SHA256(bz) + return shasum[:20] +} +``` ### Simple Merkle Root @@ -174,7 +182,7 @@ func SimpleMerkleRoot(hashes [][]byte) []byte{ func SimpleConcatHash(left, right []byte) []byte{ left = encodeByteSlice(left) right = encodeByteSlice(right) - return RIPEMD160 (append(left, right)) + return TMHASH(append(left, right)) } ``` @@ -182,8 +190,8 @@ Note that the leaves are Amino encoded as byte-arrays (ie. simple Uvarint length prefix) before being concatenated together and hashed. Note: we will abuse notion and invoke `SimpleMerkleRoot` with arguments of type `struct` or type `[]struct`. -For `struct` arguments, we compute a `[][]byte` by sorting elements of the `struct` according to -field name and then hashing them. +For `struct` arguments, we compute a `[][]byte` containing the hash of each +field in the struct sorted by the hash of the field name. For `[]struct` arguments, we compute a `[][]byte` by hashing the individual `struct` elements. ### Simple Merkle Proof diff --git a/types/block.go b/types/block.go index c3a399f67..bc018ee89 100644 --- a/types/block.go +++ b/types/block.go @@ -8,9 +8,9 @@ import ( "sync" "time" + "github.com/tendermint/tendermint/crypto/merkle" + "github.com/tendermint/tendermint/crypto/tmhash" cmn "github.com/tendermint/tendermint/libs/common" - "github.com/tendermint/tendermint/libs/merkle" - "golang.org/x/crypto/ripemd160" ) // Block defines the atomic unit of a Tendermint blockchain. @@ -552,7 +552,7 @@ type hasher struct { } func (h hasher) Hash() []byte { - hasher := ripemd160.New() + hasher := tmhash.New() if h.item != nil && !cmn.IsTypedNil(h.item) && !cmn.IsEmpty(h.item) { bz, err := cdc.MarshalBinaryBare(h.item) if err != nil { diff --git a/types/evidence.go b/types/evidence.go index a83e2cd00..266375ec3 100644 --- a/types/evidence.go +++ b/types/evidence.go @@ -5,8 +5,9 @@ import ( "fmt" "github.com/tendermint/go-amino" + "github.com/tendermint/tendermint/crypto" - "github.com/tendermint/tendermint/libs/merkle" + "github.com/tendermint/tendermint/crypto/merkle" ) // ErrEvidenceInvalid wraps a piece of evidence and the error denoting how or why it is invalid. @@ -180,7 +181,7 @@ type EvidenceList []Evidence // Hash returns the simple merkle root hash of the EvidenceList. func (evl EvidenceList) Hash() []byte { // Recursive impl. - // Copied from tmlibs/merkle to avoid allocations + // Copied from crypto/merkle to avoid allocations switch len(evl) { case 0: return nil diff --git a/types/params.go b/types/params.go index e2117ed4c..3056c82a0 100644 --- a/types/params.go +++ b/types/params.go @@ -2,8 +2,8 @@ package types import ( abci "github.com/tendermint/tendermint/abci/types" + "github.com/tendermint/tendermint/crypto/merkle" cmn "github.com/tendermint/tendermint/libs/common" - "github.com/tendermint/tendermint/libs/merkle" ) const ( diff --git a/types/part_set.go b/types/part_set.go index 7116176d3..f6d7f6b6e 100644 --- a/types/part_set.go +++ b/types/part_set.go @@ -7,10 +7,9 @@ import ( "io" "sync" - "golang.org/x/crypto/ripemd160" - + "github.com/tendermint/tendermint/crypto/merkle" + "github.com/tendermint/tendermint/crypto/tmhash" cmn "github.com/tendermint/tendermint/libs/common" - "github.com/tendermint/tendermint/libs/merkle" ) var ( @@ -31,7 +30,7 @@ func (part *Part) Hash() []byte { if part.hash != nil { return part.hash } - hasher := ripemd160.New() + hasher := tmhash.New() hasher.Write(part.Bytes) // nolint: errcheck, gas part.hash = hasher.Sum(nil) return part.hash diff --git a/types/results.go b/types/results.go index d9381420a..7f8e6093a 100644 --- a/types/results.go +++ b/types/results.go @@ -2,8 +2,8 @@ package types import ( abci "github.com/tendermint/tendermint/abci/types" + "github.com/tendermint/tendermint/crypto/merkle" cmn "github.com/tendermint/tendermint/libs/common" - "github.com/tendermint/tendermint/libs/merkle" ) //----------------------------------------------------------------------------- @@ -51,6 +51,8 @@ func (a ABCIResults) Bytes() []byte { // Hash returns a merkle hash of all results func (a ABCIResults) Hash() []byte { + // NOTE: we copy the impl of the merkle tree for txs - + // we should be consistent and either do it for both or not. return merkle.SimpleHashFromHashers(a.toHashers()) } diff --git a/types/tx.go b/types/tx.go index d02dc7a17..489f0b232 100644 --- a/types/tx.go +++ b/types/tx.go @@ -6,19 +6,19 @@ import ( "fmt" abci "github.com/tendermint/tendermint/abci/types" + "github.com/tendermint/tendermint/crypto/merkle" + "github.com/tendermint/tendermint/crypto/tmhash" cmn "github.com/tendermint/tendermint/libs/common" - "github.com/tendermint/tendermint/libs/merkle" ) // Tx is an arbitrary byte array. // NOTE: Tx has no types at this level, so when wire encoded it's just length-prefixed. -// Alternatively, it may make sense to add types here and let -// []byte be type 0x1 so we can have versioned txs if need be in the future. +// Might we want types here ? type Tx []byte -// Hash computes the RIPEMD160 hash of the wire encoded transaction. +// Hash computes the TMHASH hash of the wire encoded transaction. func (tx Tx) Hash() []byte { - return aminoHasher(tx).Hash() + return tmhash.Sum(tx) } // String returns the hex-encoded transaction as a string. @@ -32,7 +32,7 @@ type Txs []Tx // Hash returns the simple Merkle root hash of the transactions. func (txs Txs) Hash() []byte { // Recursive impl. - // Copied from tmlibs/merkle to avoid allocations + // Copied from tendermint/crypto/merkle to avoid allocations switch len(txs) { case 0: return nil diff --git a/types/validator_set.go b/types/validator_set.go index 6c39f5be2..191f8b428 100644 --- a/types/validator_set.go +++ b/types/validator_set.go @@ -7,8 +7,8 @@ import ( "sort" "strings" + "github.com/tendermint/tendermint/crypto/merkle" cmn "github.com/tendermint/tendermint/libs/common" - "github.com/tendermint/tendermint/libs/merkle" ) // ValidatorSet represent a set of *Validator at a given height.