From 32e001c44649e4692ff4aceabe60c66e43b144f9 Mon Sep 17 00:00:00 2001
From: Brannon King <countprimes@gmail.com>
Date: Thu, 12 Aug 2021 12:28:08 -0400
Subject: [PATCH] ignore empty claims in the hash computation

---
 claimtrie/claimtrie.go         |  4 ++-
 claimtrie/node/hash_manager.go | 63 ++++++++++++++++++++++++++++++++++
 claimtrie/node/manager.go      |  2 +-
 claimtrie/node/manager_test.go |  4 +--
 4 files changed, 69 insertions(+), 4 deletions(-)
 create mode 100644 claimtrie/node/hash_manager.go

diff --git a/claimtrie/claimtrie.go b/claimtrie/claimtrie.go
index 05d423be..04352485 100644
--- a/claimtrie/claimtrie.go
+++ b/claimtrie/claimtrie.go
@@ -89,7 +89,9 @@ func New(cfg config.Config) (*ClaimTrie, error) {
 		return nil, errors.Wrap(err, "creating node base manager")
 	}
 	normalizingManager := node.NewNormalizingManager(baseManager)
-	nodeManager := &node.HashV2Manager{Manager: normalizingManager}
+	hashV2Manager := &node.HashV2Manager{Manager: normalizingManager}
+	nodeManager := &node.HashV3Manager{Manager: hashV2Manager}
+
 	cleanups = append(cleanups, nodeManager.Close)
 
 	var trie merkletrie.MerkleTrie
diff --git a/claimtrie/node/hash_manager.go b/claimtrie/node/hash_manager.go
new file mode 100644
index 00000000..4892cac4
--- /dev/null
+++ b/claimtrie/node/hash_manager.go
@@ -0,0 +1,63 @@
+package node
+
+import (
+	"github.com/btcsuite/btcd/chaincfg/chainhash"
+	"github.com/lbryio/chain/claimtrie/change"
+	"github.com/lbryio/chain/claimtrie/param"
+)
+
+type HashV2Manager struct {
+	Manager
+}
+
+type HashV3Manager struct {
+	Manager
+}
+
+func (nm *HashV2Manager) claimHashes(name []byte) (*chainhash.Hash, int32) {
+
+	n, err := nm.NodeAt(nm.Height(), name)
+	if err != nil || n == nil {
+		return nil, 0
+	}
+
+	n.SortClaimsByBid()
+	claimHashes := make([]*chainhash.Hash, 0, len(n.Claims))
+	for _, c := range n.Claims {
+		if c.Status == Activated { // TODO: unit test this line
+			claimHashes = append(claimHashes, calculateNodeHash(c.OutPoint, n.TakenOverAt))
+		}
+	}
+	if len(claimHashes) > 0 {
+		return ComputeMerkleRoot(claimHashes), n.NextUpdate(nm.Height())
+	}
+	return nil, n.NextUpdate(nm.Height())
+}
+
+func (nm *HashV2Manager) Hash(name []byte) (*chainhash.Hash, int32) {
+
+	if nm.Height() >= param.ActiveParams.AllClaimsInMerkleForkHeight {
+		return nm.claimHashes(name)
+	}
+
+	return nm.Manager.Hash(name)
+}
+
+func (nm *HashV3Manager) AppendChange(chg change.Change) {
+	if nm.Height() >= param.ActiveParams.GrandForkHeight && len(chg.Name) == 0 {
+		return
+	}
+	nm.Manager.AppendChange(chg)
+}
+
+func (nm *HashV3Manager) Hash(name []byte) (*chainhash.Hash, int32) {
+
+	if nm.Height() >= param.ActiveParams.GrandForkHeight {
+		if len(name) == 0 {
+			return nil, 0 // empty name's claims are not included in the hash
+		}
+		// return nm.detailHash()
+	}
+
+	return nm.Manager.Hash(name)
+}
diff --git a/claimtrie/node/manager.go b/claimtrie/node/manager.go
index 5b200c31..d089ac6e 100644
--- a/claimtrie/node/manager.go
+++ b/claimtrie/node/manager.go
@@ -187,7 +187,7 @@ func (nm *BaseManager) IncrementHeightTo(height int32) ([][]byte, error) {
 		panic("invalid height")
 	}
 
-	if height >= param.ActiveParams.MaxRemovalWorkaroundHeight {
+	if height >= param.ActiveParams.MaxRemovalWorkaroundHeight && height < param.ActiveParams.GrandForkHeight {
 		// not technically needed until block 884430, but to be true to the arbitrary rollback length...
 		collectChildNames(nm.changes)
 	}
diff --git a/claimtrie/node/manager_test.go b/claimtrie/node/manager_test.go
index 83c4d470..b63dac2f 100644
--- a/claimtrie/node/manager_test.go
+++ b/claimtrie/node/manager_test.go
@@ -271,7 +271,7 @@ func TestEndOfExpiration(t *testing.T) {
 	r.NoError(err)
 	n, err := m.NodeAt(m.height, name1)
 	r.NoError(err)
-	r.Equal(m.height + param.ActiveParams.ExtendedClaimExpirationTime, n.NextUpdate(m.height))
+	r.Equal(m.height+param.ActiveParams.ExtendedClaimExpirationTime, n.NextUpdate(m.height))
 
 	_, err = m.IncrementHeightTo(gf)
 	r.NoError(err)
@@ -279,4 +279,4 @@ func TestEndOfExpiration(t *testing.T) {
 	n, err = m.NodeAt(m.height, name1)
 	r.NoError(err)
 	r.Equal(int32(0), n.NextUpdate(m.height))
-}
\ No newline at end of file
+}