Make txs and evidencelist use merkle.SimpleHashFromBytes to create hash (#2635)
This is a performance regression, but will also spare the types directory from knowing about RFC 6962, which is a more correct abstraction. For txs this performance hit will be fixed soon with #2603. For evidence, the performance impact is negligible due to it being capped at a small number.
This commit is contained in:
parent
4ab7dcf3ac
commit
124d0db1e0
|
@ -24,6 +24,7 @@ BREAKING CHANGES:
|
|||
* [types] \#2298 Remove `Index` and `Total` fields from `TxProof`.
|
||||
* [crypto/merkle & lite] \#2298 Various changes to accomodate General Merkle trees
|
||||
* [crypto/merkle] \#2595 Remove all Hasher objects in favor of byte slices
|
||||
* [crypto/merkle] \#2635 merkle.SimpleHashFromTwoHashes is no longer exported
|
||||
* [types] \#2598 `VoteTypeXxx` are now
|
||||
|
||||
* Blockchain Protocol
|
||||
|
|
|
@ -134,13 +134,13 @@ func computeHashFromAunts(index int, total int, leafHash []byte, innerHashes [][
|
|||
if leftHash == nil {
|
||||
return nil
|
||||
}
|
||||
return SimpleHashFromTwoHashes(leftHash, innerHashes[len(innerHashes)-1])
|
||||
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)
|
||||
return simpleHashFromTwoHashes(innerHashes[len(innerHashes)-1], rightHash)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -187,7 +187,7 @@ func trailsFromByteSlices(items [][]byte) (trails []*SimpleProofNode, root *Simp
|
|||
default:
|
||||
lefts, leftRoot := trailsFromByteSlices(items[:(len(items)+1)/2])
|
||||
rights, rightRoot := trailsFromByteSlices(items[(len(items)+1)/2:])
|
||||
rootHash := SimpleHashFromTwoHashes(leftRoot.Hash, rightRoot.Hash)
|
||||
rootHash := simpleHashFromTwoHashes(leftRoot.Hash, rightRoot.Hash)
|
||||
root := &SimpleProofNode{rootHash, nil, nil, nil}
|
||||
leftRoot.Parent = root
|
||||
leftRoot.Right = rightRoot
|
||||
|
|
|
@ -4,8 +4,8 @@ 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 {
|
||||
// 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 {
|
||||
|
@ -29,7 +29,7 @@ func SimpleHashFromByteSlices(items [][]byte) []byte {
|
|||
default:
|
||||
left := SimpleHashFromByteSlices(items[:(len(items)+1)/2])
|
||||
right := SimpleHashFromByteSlices(items[(len(items)+1)/2:])
|
||||
return SimpleHashFromTwoHashes(left, right)
|
||||
return simpleHashFromTwoHashes(left, right)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -576,7 +576,6 @@ func (sh SignedHeader) StringIndented(indent string) string {
|
|||
indent, sh.Header.StringIndented(indent+" "),
|
||||
indent, sh.Commit.StringIndented(indent+" "),
|
||||
indent)
|
||||
return ""
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -660,7 +659,6 @@ func (data *EvidenceData) StringIndented(indent string) string {
|
|||
%s}#%v`,
|
||||
indent, strings.Join(evStrings, "\n"+indent+" "),
|
||||
indent, data.hash)
|
||||
return ""
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
|
|
|
@ -55,6 +55,7 @@ func (err *ErrEvidenceOverflow) Error() string {
|
|||
type Evidence interface {
|
||||
Height() int64 // height of the equivocation
|
||||
Address() []byte // address of the equivocating validator
|
||||
Bytes() []byte // bytes which compromise the evidence
|
||||
Hash() []byte // hash of the evidence
|
||||
Verify(chainID string, pubKey crypto.PubKey) error // verify the evidence
|
||||
Equal(Evidence) bool // check equality of evidence
|
||||
|
@ -88,6 +89,8 @@ type DuplicateVoteEvidence struct {
|
|||
VoteB *Vote
|
||||
}
|
||||
|
||||
var _ Evidence = &DuplicateVoteEvidence{}
|
||||
|
||||
// String returns a string representation of the evidence.
|
||||
func (dve *DuplicateVoteEvidence) String() string {
|
||||
return fmt.Sprintf("VoteA: %v; VoteB: %v", dve.VoteA, dve.VoteB)
|
||||
|
@ -104,6 +107,11 @@ func (dve *DuplicateVoteEvidence) Address() []byte {
|
|||
return dve.PubKey.Address()
|
||||
}
|
||||
|
||||
// Hash returns the hash of the evidence.
|
||||
func (dve *DuplicateVoteEvidence) Bytes() []byte {
|
||||
return cdcEncode(dve)
|
||||
}
|
||||
|
||||
// Hash returns the hash of the evidence.
|
||||
func (dve *DuplicateVoteEvidence) Hash() []byte {
|
||||
return tmhash.Sum(cdcEncode(dve))
|
||||
|
@ -172,6 +180,8 @@ type MockGoodEvidence struct {
|
|||
Address_ []byte
|
||||
}
|
||||
|
||||
var _ Evidence = &MockGoodEvidence{}
|
||||
|
||||
// UNSTABLE
|
||||
func NewMockGoodEvidence(height int64, idx int, address []byte) MockGoodEvidence {
|
||||
return MockGoodEvidence{height, address}
|
||||
|
@ -182,6 +192,9 @@ func (e MockGoodEvidence) Address() []byte { return e.Address_ }
|
|||
func (e MockGoodEvidence) Hash() []byte {
|
||||
return []byte(fmt.Sprintf("%d-%x", e.Height_, e.Address_))
|
||||
}
|
||||
func (e MockGoodEvidence) Bytes() []byte {
|
||||
return []byte(fmt.Sprintf("%d-%x", e.Height_, e.Address_))
|
||||
}
|
||||
func (e MockGoodEvidence) Verify(chainID string, pubKey crypto.PubKey) error { return nil }
|
||||
func (e MockGoodEvidence) Equal(ev Evidence) bool {
|
||||
e2 := ev.(MockGoodEvidence)
|
||||
|
@ -216,18 +229,14 @@ type EvidenceList []Evidence
|
|||
|
||||
// Hash returns the simple merkle root hash of the EvidenceList.
|
||||
func (evl EvidenceList) Hash() []byte {
|
||||
// Recursive impl.
|
||||
// Copied from crypto/merkle to avoid allocations
|
||||
switch len(evl) {
|
||||
case 0:
|
||||
return nil
|
||||
case 1:
|
||||
return evl[0].Hash()
|
||||
default:
|
||||
left := EvidenceList(evl[:(len(evl)+1)/2]).Hash()
|
||||
right := EvidenceList(evl[(len(evl)+1)/2:]).Hash()
|
||||
return merkle.SimpleHashFromTwoHashes(left, right)
|
||||
// These allocations are required because Evidence is not of type Bytes, and
|
||||
// golang slices can't be typed cast. This shouldn't be a performance problem since
|
||||
// the Evidence size is capped.
|
||||
evidenceBzs := make([][]byte, len(evl))
|
||||
for i := 0; i < len(evl); i++ {
|
||||
evidenceBzs[i] = evl[i].Bytes()
|
||||
}
|
||||
return merkle.SimpleHashFromByteSlices(evidenceBzs)
|
||||
}
|
||||
|
||||
func (evl EvidenceList) String() string {
|
||||
|
|
17
types/tx.go
17
types/tx.go
|
@ -31,18 +31,13 @@ type Txs []Tx
|
|||
|
||||
// Hash returns the simple Merkle root hash of the transactions.
|
||||
func (txs Txs) Hash() []byte {
|
||||
// Recursive impl.
|
||||
// Copied from tendermint/crypto/merkle to avoid allocations
|
||||
switch len(txs) {
|
||||
case 0:
|
||||
return nil
|
||||
case 1:
|
||||
return txs[0].Hash()
|
||||
default:
|
||||
left := Txs(txs[:(len(txs)+1)/2]).Hash()
|
||||
right := Txs(txs[(len(txs)+1)/2:]).Hash()
|
||||
return merkle.SimpleHashFromTwoHashes(left, right)
|
||||
// These allocations will be removed once Txs is switched to [][]byte,
|
||||
// ref #2603. This is because golang does not allow type casting slices without unsafe
|
||||
txBzs := make([][]byte, len(txs))
|
||||
for i := 0; i < len(txs); i++ {
|
||||
txBzs[i] = txs[i]
|
||||
}
|
||||
return merkle.SimpleHashFromByteSlices(txBzs)
|
||||
}
|
||||
|
||||
// Index returns the index of this transaction in the list, or -1 if not found
|
||||
|
|
Loading…
Reference in New Issue