diff --git a/blockchain/difficulty.go b/blockchain/difficulty.go index b9662195..b0f5f195 100644 --- a/blockchain/difficulty.go +++ b/blockchain/difficulty.go @@ -57,15 +57,14 @@ var ( // perform math comparisons. func ShaHashToBig(hash *wire.ShaHash) *big.Int { // A ShaHash is in little-endian, but the big package wants the bytes - // in big-endian. Reverse them. ShaHash.Bytes makes a copy, so it - // is safe to modify the returned buffer. - buf := hash.Bytes() + // in big-endian, so reverse them. + buf := *hash blen := len(buf) for i := 0; i < blen/2; i++ { buf[i], buf[blen-1-i] = buf[blen-1-i], buf[i] } - return new(big.Int).SetBytes(buf) + return new(big.Int).SetBytes(buf[:]) } // CompactToBig converts a compact representation of a whole number N to an diff --git a/blockchain/merkle.go b/blockchain/merkle.go index 13c901dd..5d7e6367 100644 --- a/blockchain/merkle.go +++ b/blockchain/merkle.go @@ -31,8 +31,8 @@ func nextPowerOfTwo(n int) int { func HashMerkleBranches(left *wire.ShaHash, right *wire.ShaHash) *wire.ShaHash { // Concatenate the left and right nodes. var sha [wire.HashSize * 2]byte - copy(sha[:wire.HashSize], left.Bytes()) - copy(sha[wire.HashSize:], right.Bytes()) + copy(sha[:wire.HashSize], left[:]) + copy(sha[wire.HashSize:], right[:]) // Create a new sha hash from the double sha 256. Ignore the error // here since SetBytes can't fail here due to the fact DoubleSha256 diff --git a/database/ldb/block.go b/database/ldb/block.go index 7e2f8ff2..5533f69a 100644 --- a/database/ldb/block.go +++ b/database/ldb/block.go @@ -134,10 +134,9 @@ func (db *LevelDb) setBlk(sha *wire.ShaHash, blkHeight int64, buf []byte) { shaKey := shaBlkToKey(sha) blkKey := int64ToKey(blkHeight) - shaB := sha.Bytes() - blkVal := make([]byte, len(shaB)+len(buf)) - copy(blkVal[0:], shaB) - copy(blkVal[len(shaB):], buf) + blkVal := make([]byte, len(sha)+len(buf)) + copy(blkVal[0:], sha[:]) + copy(blkVal[len(sha):], buf) db.lBatch().Put(shaKey, lw[:]) db.lBatch().Put(blkKey, blkVal) diff --git a/database/ldb/leveldb.go b/database/ldb/leveldb.go index 64af1663..9a10f349 100644 --- a/database/ldb/leveldb.go +++ b/database/ldb/leveldb.go @@ -641,8 +641,7 @@ func int64ToKey(keyint int64) []byte { } func shaBlkToKey(sha *wire.ShaHash) []byte { - shaB := sha.Bytes() - return shaB + return sha[:] } // These are used here and in tx.go's deleteOldAddrIndex() to prevent deletion @@ -651,15 +650,17 @@ var recordSuffixTx = []byte{'t', 'x'} var recordSuffixSpentTx = []byte{'s', 'x'} func shaTxToKey(sha *wire.ShaHash) []byte { - shaB := sha.Bytes() - shaB = append(shaB, recordSuffixTx...) - return shaB + key := make([]byte, len(sha)+len(recordSuffixTx)) + copy(key, sha[:]) + copy(key[len(sha):], recordSuffixTx) + return key } func shaSpentTxToKey(sha *wire.ShaHash) []byte { - shaB := sha.Bytes() - shaB = append(shaB, recordSuffixSpentTx...) - return shaB + key := make([]byte, len(sha)+len(recordSuffixSpentTx)) + copy(key, sha[:]) + copy(key[len(sha):], recordSuffixSpentTx) + return key } func (db *LevelDb) lBatch() *leveldb.Batch { diff --git a/database/ldb/tx.go b/database/ldb/tx.go index 4f834e76..7fff041e 100644 --- a/database/ldb/tx.go +++ b/database/ldb/tx.go @@ -537,7 +537,7 @@ func (db *LevelDb) UpdateAddrIndexForBlock(blkSha *wire.ShaHash, blkHeight int64 // Update tip of addrindex. newIndexTip := make([]byte, 40, 40) - copy(newIndexTip[0:32], blkSha.Bytes()) + copy(newIndexTip[0:32], blkSha[:]) binary.LittleEndian.PutUint64(newIndexTip[32:40], uint64(blkHeight)) batch.Put(addrIndexMetaDataKey, newIndexTip) diff --git a/server.go b/server.go index a24a2817..9a17c60e 100644 --- a/server.go +++ b/server.go @@ -5,7 +5,6 @@ package main import ( - "bytes" "container/list" "crypto/rand" "encoding/binary" @@ -215,13 +214,15 @@ func (s *server) handleUpdatePeerHeights(state *peerState, umsg updatePeerHeight return } - latestBlkSha := p.lastAnnouncedBlock.Bytes() + // This is a pointer to the underlying memory which doesn't + // change. + latestBlkSha := p.lastAnnouncedBlock p.StatsMtx.Unlock() // If the peer has recently announced a block, and this block // matches our newly accepted block, then update their block // height. - if bytes.Equal(latestBlkSha, umsg.newSha.Bytes()) { + if *latestBlkSha == *umsg.newSha { p.UpdateLastBlockHeight(umsg.newHeight) p.UpdateLastAnnouncedBlock(nil) } diff --git a/wire/bench_test.go b/wire/bench_test.go index 3c0350ee..b7d2b7d5 100644 --- a/wire/bench_test.go +++ b/wire/bench_test.go @@ -392,3 +392,20 @@ func BenchmarkTxSha(b *testing.B) { genesisCoinbaseTx.TxSha() } } + +// BenchmarkDoubleSha256 performs a benchmark on how long it takes to perform a +// double sha 256. +func BenchmarkDoubleSha256(b *testing.B) { + b.StopTimer() + var buf bytes.Buffer + if err := genesisCoinbaseTx.Serialize(&buf); err != nil { + b.Errorf("Serialize: unexpected error: %v", err) + return + } + txBytes := buf.Bytes() + b.StartTimer() + + for i := 0; i < b.N; i++ { + _ = DoubleSha256(txBytes) + } +} diff --git a/wire/common.go b/wire/common.go index bf41d68e..27264951 100644 --- a/wire/common.go +++ b/wire/common.go @@ -522,10 +522,7 @@ func RandomUint64() (uint64, error) { // DoubleSha256 calculates sha256(sha256(b)) and returns the resulting bytes. func DoubleSha256(b []byte) []byte { - hasher := fastsha256.New() - hasher.Write(b) - sum := hasher.Sum(nil) - hasher.Reset() - hasher.Write(sum) - return hasher.Sum(nil) + first := fastsha256.Sum256(b) + second := fastsha256.Sum256(first[:]) + return second[:] } diff --git a/wire/shahash.go b/wire/shahash.go index 63f30ac0..41ca3f66 100644 --- a/wire/shahash.go +++ b/wire/shahash.go @@ -5,7 +5,6 @@ package wire import ( - "bytes" "encoding/hex" "fmt" ) @@ -34,6 +33,10 @@ func (hash ShaHash) String() string { } // Bytes returns the bytes which represent the hash as a byte slice. +// +// NOTE: This makes a copy of the bytes and should have probably been named +// CloneBytes. It is generally cheaper to just slice the hash directly thereby +// reusing the same bytes rather than calling this method. func (hash *ShaHash) Bytes() []byte { newHash := make([]byte, HashSize) copy(newHash, hash[:]) @@ -49,14 +52,14 @@ func (hash *ShaHash) SetBytes(newHash []byte) error { return fmt.Errorf("invalid sha length of %v, want %v", nhlen, HashSize) } - copy(hash[:], newHash[0:HashSize]) + copy(hash[:], newHash) return nil } // IsEqual returns true if target is the same as hash. func (hash *ShaHash) IsEqual(target *ShaHash) bool { - return bytes.Equal(hash[:], target[:]) + return *hash == *target } // NewShaHash returns a new ShaHash from a byte slice. An error is returned if