Skip to content

Change hash representation from slice to 32-byte array #505

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 11 additions & 14 deletions common/cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"path/filepath"
"sync"

"github.com/zcash/lightwalletd/hash32"
"github.com/zcash/lightwalletd/walletrpc"
"google.golang.org/protobuf/proto"
)
Expand All @@ -22,10 +23,10 @@ import (
type BlockCache struct {
lengthsName, blocksName string // pathnames
lengthsFile, blocksFile *os.File
starts []int64 // Starting offset of each block within blocksFile
firstBlock int // height of the first block in the cache (usually Sapling activation)
nextBlock int // height of the first block not in the cache
latestHash []byte // hash of the most recent (highest height) block, for detecting reorgs.
starts []int64 // Starting offset of each block within blocksFile
firstBlock int // height of the first block in the cache (usually Sapling activation)
nextBlock int // height of the first block not in the cache
latestHash hash32.T // hash of the most recent (highest height) block, for detecting reorgs.
mutex sync.RWMutex
}

Expand All @@ -44,18 +45,18 @@ func (c *BlockCache) GetFirstHeight() int {
}

// GetLatestHash returns the hash (block ID) of the most recent (highest) known block.
func (c *BlockCache) GetLatestHash() []byte {
func (c *BlockCache) GetLatestHash() hash32.T {
c.mutex.RLock()
defer c.mutex.RUnlock()
return c.latestHash
}

// HashMatch indicates if the given prev-hash matches the most recent block's hash
// so reorgs can be detected.
func (c *BlockCache) HashMatch(prevhash []byte) bool {
func (c *BlockCache) HashMatch(prevhash hash32.T) bool {
c.mutex.RLock()
defer c.mutex.RUnlock()
return c.latestHash == nil || bytes.Equal(c.latestHash, prevhash)
return c.latestHash == hash32.Nil || c.latestHash == prevhash
}

// Make the block at the given height the lowest height that we don't have.
Expand Down Expand Up @@ -167,7 +168,7 @@ func (c *BlockCache) readBlock(height int) *walletrpc.CompactBlock {

// Caller should hold c.mutex.Lock().
func (c *BlockCache) setLatestHash() {
c.latestHash = nil
c.latestHash = hash32.Nil
// There is at least one block; get the last block's hash
if c.nextBlock > c.firstBlock {
// At least one block remains; get the last block's hash
Expand All @@ -176,8 +177,7 @@ func (c *BlockCache) setLatestHash() {
c.recoverFromCorruption(c.nextBlock - 10000)
return
}
c.latestHash = make([]byte, len(block.Hash))
copy(c.latestHash, block.Hash)
c.latestHash = hash32.T(block.Hash)
}
}

Expand Down Expand Up @@ -312,10 +312,7 @@ func (c *BlockCache) Add(height int, block *walletrpc.CompactBlock) error {
offset := c.starts[len(c.starts)-1]
c.starts = append(c.starts, offset+int64(len(data)+8))

if c.latestHash == nil {
c.latestHash = make([]byte, len(block.Hash))
}
copy(c.latestHash, block.Hash)
c.latestHash = hash32.T(block.Hash)
c.nextBlock++
// Invariant: m[firstBlock..nextBlock) are valid.
return nil
Expand Down
3 changes: 2 additions & 1 deletion common/cache_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"os"
"testing"

"github.com/zcash/lightwalletd/hash32"
"github.com/zcash/lightwalletd/parser"
"github.com/zcash/lightwalletd/walletrpc"
)
Expand Down Expand Up @@ -84,7 +85,7 @@ func TestCache(t *testing.T) {

// Reorg to before the first block moves back to only the first block
cache.Reorg(289459)
if cache.latestHash != nil {
if cache.latestHash != hash32.Nil {
t.Fatal("unexpected latestHash, should be nil")
}
if cache.nextBlock != 289460 {
Expand Down
55 changes: 28 additions & 27 deletions common/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"time"

"github.com/sirupsen/logrus"
"github.com/zcash/lightwalletd/hash32"
"github.com/zcash/lightwalletd/parser"
"github.com/zcash/lightwalletd/walletrpc"
)
Expand Down Expand Up @@ -369,12 +370,12 @@ func getBlockFromRPC(height int) (*walletrpc.CompactBlock, error) {
return nil, errors.New("received unexpected height block")
}
for i, t := range block.Transactions() {
txid, err := hex.DecodeString(block1.Tx[i])
txid, err := hash32.Decode(block1.Tx[i])
if err != nil {
return nil, fmt.Errorf("error decoding getblock txid: %w", err)
}
// convert from big-endian
t.SetTxID(parser.Reverse(txid))
t.SetTxID(hash32.Reverse(txid))
}
r := block.ToCompact()
r.ChainMetadata.SaplingCommitmentTreeSize = block1.Trees.Sapling.Size
Expand Down Expand Up @@ -426,13 +427,13 @@ func BlockIngestor(c *BlockCache, rep int) {
if err != nil {
Log.Fatal("bad getbestblockhash return:", err, result)
}
lastBestBlockHash, err := hex.DecodeString(hashHex)
lastBestBlockHash, err := hash32.Decode(hashHex)
if err != nil {
Log.Fatal("error decoding getbestblockhash", err, hashHex)
}

height := c.GetNextHeight()
if string(lastBestBlockHash) == string(parser.Reverse(c.GetLatestHash())) {
if lastBestBlockHash == hash32.Reverse(c.GetLatestHash()) {
// Synced
c.Sync()
if lastHeightLogged != height-1 {
Expand All @@ -450,14 +451,14 @@ func BlockIngestor(c *BlockCache, rep int) {
Time.Sleep(8 * time.Second)
continue
}
if block != nil && c.HashMatch(block.PrevHash) {
if block != nil && c.HashMatch(hash32.T(block.PrevHash)) {
if err = c.Add(height, block); err != nil {
Log.Fatal("Cache add failed:", err)
}
// Don't log these too often.
if DarksideEnabled || Time.Now().Sub(lastLog).Seconds() >= 4 {
lastLog = Time.Now()
Log.Info("Adding block to cache ", height, " ", displayHash(block.Hash))
Log.Info("Adding block to cache ", height, " ", displayHash(hash32.T(block.Hash)))
}
continue
}
Expand Down Expand Up @@ -537,29 +538,29 @@ func GetBlockRange(cache *BlockCache, blockOut chan<- *walletrpc.CompactBlock, e
// the meanings of the `Height` field of the `RawTransaction` type are as
// follows:
//
// * height 0: the transaction is in the mempool
// * height 0xffffffffffffffff: the transaction has been mined on a fork that
// is not currently the main chain
// * any other height: the transaction has been mined in the main chain at the
// given height
// - height 0: the transaction is in the mempool
// - height 0xffffffffffffffff: the transaction has been mined on a fork that
// is not currently the main chain
// - any other height: the transaction has been mined in the main chain at the
// given height
func ParseRawTransaction(message json.RawMessage) (*walletrpc.RawTransaction, error) {
// Many other fields are returned, but we need only these two.
var txinfo ZcashdRpcReplyGetrawtransaction
err := json.Unmarshal(message, &txinfo)
if err != nil {
return nil, err
}
txBytes, err := hex.DecodeString(txinfo.Hex)
if err != nil {
return nil, err
}
// Many other fields are returned, but we need only these two.
var txinfo ZcashdRpcReplyGetrawtransaction
err := json.Unmarshal(message, &txinfo)
if err != nil {
return nil, err
}
txBytes, err := hex.DecodeString(txinfo.Hex)
if err != nil {
return nil, err
}

return &walletrpc.RawTransaction{
Data: txBytes,
Height: uint64(txinfo.Height),
}, nil
return &walletrpc.RawTransaction{
Data: txBytes,
Height: uint64(txinfo.Height),
}, nil
}

func displayHash(hash []byte) string {
return hex.EncodeToString(parser.Reverse(hash))
func displayHash(hash hash32.T) string {
return hash32.Encode(hash32.Reverse(hash))
}
Loading