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:
Dev Ojha
2018-10-15 15:42:47 -05:00
committed by Ethan Buchman
parent 4ab7dcf3ac
commit 124d0db1e0
6 changed files with 33 additions and 30 deletions

View File

@ -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 ""
}
//--------------------------------------------------------------------------------

View File

@ -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 {

View File

@ -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