From 1f3482c7e4c5ed15256913e939ab1fe3990798be Mon Sep 17 00:00:00 2001 From: Brannon King Date: Sat, 24 Jun 2023 14:27:09 -0400 Subject: [PATCH 1/7] made claims never expire --- claimtrie/node/hashfork_manager.go | 4 +-- claimtrie/node/manager.go | 12 ++----- claimtrie/node/manager_test.go | 50 ++++++++++++++++++++++++------ claimtrie/node/node.go | 29 +++++++++++------ claimtrie/param/general.go | 4 +++ 5 files changed, 70 insertions(+), 29 deletions(-) diff --git a/claimtrie/node/hashfork_manager.go b/claimtrie/node/hashfork_manager.go index bbd814eecb..b25c631c9b 100644 --- a/claimtrie/node/hashfork_manager.go +++ b/claimtrie/node/hashfork_manager.go @@ -24,9 +24,9 @@ func (nm *HashV2Manager) computeClaimHashes(name []byte) (*chainhash.Hash, int32 } } if len(claimHashes) > 0 { - return ComputeMerkleRoot(claimHashes), n.NextUpdate() + return ComputeMerkleRoot(claimHashes), n.NextUpdate(nm.Height()) } - return nil, n.NextUpdate() + return nil, n.NextUpdate(nm.Height()) } func (nm *HashV2Manager) Hash(name []byte) (*chainhash.Hash, int32) { diff --git a/claimtrie/node/manager.go b/claimtrie/node/manager.go index 7081ac250f..4048c13fa9 100644 --- a/claimtrie/node/manager.go +++ b/claimtrie/node/manager.go @@ -92,12 +92,6 @@ func (nm *BaseManager) NodeAt(height int32, name []byte) (*Node, error) { return n, nil } -// Node returns a node at the current height. -// The returned node may have pending changes. -func (nm *BaseManager) node(name []byte) (*Node, error) { - return nm.NodeAt(nm.height, name) -} - func (nm *BaseManager) updateFromChanges(n *Node, changes []change.Change, height int32) (bool, error) { count := len(changes) @@ -436,17 +430,17 @@ func (nm *BaseManager) IterateNames(predicate func(name []byte) bool) { func (nm *BaseManager) Hash(name []byte) (*chainhash.Hash, int32) { - n, err := nm.node(name) + n, err := nm.NodeAt(nm.height, name) if err != nil || n == nil { return nil, 0 } if len(n.Claims) > 0 { if n.BestClaim != nil && n.BestClaim.Status == Activated { h := calculateNodeHash(n.BestClaim.OutPoint, n.TakenOverAt) - return h, n.NextUpdate() + return h, n.NextUpdate(nm.height) } } - return nil, n.NextUpdate() + return nil, n.NextUpdate(nm.height) } func (nm *BaseManager) Flush() error { diff --git a/claimtrie/node/manager_test.go b/claimtrie/node/manager_test.go index c907bb4c3c..5db204e1e3 100644 --- a/claimtrie/node/manager_test.go +++ b/claimtrie/node/manager_test.go @@ -67,25 +67,25 @@ func TestSimpleAddClaim(t *testing.T) { _, err = m.IncrementHeightTo(12, false) r.NoError(err) - n1, err := m.node(name1) + n1, err := m.NodeAt(m.height, name1) r.NoError(err) r.Equal(1, len(n1.Claims)) r.NotNil(n1.Claims.find(byOut(*out1))) - n2, err := m.node(name2) + n2, err := m.NodeAt(m.height, name2) r.NoError(err) r.Equal(1, len(n2.Claims)) r.NotNil(n2.Claims.find(byOut(*out2))) _, err = m.DecrementHeightTo([][]byte{name2}, 11) r.NoError(err) - n2, err = m.node(name2) + n2, err = m.NodeAt(m.height, name2) r.NoError(err) r.Nil(n2) _, err = m.DecrementHeightTo([][]byte{name1}, 1) r.NoError(err) - n2, err = m.node(name1) + n2, err = m.NodeAt(m.height, name1) r.NoError(err) r.Nil(n2) } @@ -131,7 +131,7 @@ func TestSupportAmounts(t *testing.T) { _, err = m.IncrementHeightTo(20, false) r.NoError(err) - n1, err := m.node(name1) + n1, err := m.NodeAt(m.height, name1) r.NoError(err) r.Equal(2, len(n1.Claims)) r.Equal(int64(5), n1.BestClaim.Amount+n1.SupportSums[n1.BestClaim.ClaimID.Key()]) @@ -274,12 +274,12 @@ func TestTemporaryAddClaim(t *testing.T) { _, err = m.IncrementHeightTo(12, true) r.NoError(err) - n1, err := m.node(name1) + n1, err := m.NodeAt(m.Height(), name1) r.NoError(err) r.Equal(1, len(n1.Claims)) r.NotNil(n1.Claims.find(byOut(*out1))) - n2, err := m.node(name2) + n2, err := m.NodeAt(m.Height(), name2) r.NoError(err) r.Equal(1, len(n2.Claims)) r.NotNil(n2.Claims.find(byOut(*out2))) @@ -287,13 +287,45 @@ func TestTemporaryAddClaim(t *testing.T) { names, err := m.DecrementHeightTo([][]byte{name2}, 11) r.Equal(names[0], name2) r.NoError(err) - n2, err = m.node(name2) + n2, err = m.NodeAt(m.Height(), name2) r.NoError(err) r.Nil(n2) _, err = m.DecrementHeightTo([][]byte{name1}, 1) r.NoError(err) - n2, err = m.node(name1) + n2, err = m.NodeAt(m.Height(), name1) r.NoError(err) r.Nil(n2) } + +func TestEndOfExpiration(t *testing.T) { + r := require.New(t) + + param.SetNetwork(wire.TestNet) + repo, err := noderepo.NewPebble(t.TempDir()) + r.NoError(err) + + m, err := NewBaseManager(repo) + r.NoError(err) + defer m.Close() + + et := param.ActiveParams.ExtendedClaimExpirationForkHeight + gf := param.ActiveParams.GrandForkHeight + + chg := change.NewChange(change.AddClaim).SetName(name1).SetOutPoint(out1).SetHeight(et).SetAmount(2) + chg.ClaimID = change.NewClaimID(*out1) + m.AppendChange(chg) + + _, err = m.IncrementHeightTo(et, false) + r.NoError(err) + n, err := m.NodeAt(m.height, name1) + r.NoError(err) + r.Equal(m.height+param.ActiveParams.ExtendedClaimExpirationTime, n.NextUpdate(m.height)) + + _, err = m.IncrementHeightTo(gf, false) + r.NoError(err) + + n, err = m.NodeAt(m.height, name1) + r.NoError(err) + r.Equal(int32(0), n.NextUpdate(m.height)) +} diff --git a/claimtrie/node/node.go b/claimtrie/node/node.go index ff45fc11e1..a4bc37c3b8 100644 --- a/claimtrie/node/node.go +++ b/claimtrie/node/node.go @@ -114,7 +114,10 @@ func (n *Node) AdjustTo(height, maxHeight int32, name []byte) { changed := n.handleExpiredAndActivated(height) > 0 n.updateTakeoverHeight(height, name, changed) if maxHeight > height { - for h := n.NextUpdate(); h <= maxHeight; h = n.NextUpdate() { + for h := n.NextUpdate(height); h <= maxHeight; h = n.NextUpdate(height) { + if h <= 0 { + break + } changed = n.handleExpiredAndActivated(h) > 0 n.updateTakeoverHeight(h, name, changed) height = h @@ -176,7 +179,7 @@ func (n *Node) handleExpiredAndActivated(height int32) int { sums[c.ClaimID.Key()] += c.Amount } } - if c.Status == Deactivated || expiresAt(c) <= height { + if c.Status == Deactivated || (height < param.ActiveParams.GrandForkHeight && expiresAt(c) <= height) { if i < len(items)-1 { items[i] = items[len(items)-1] i-- @@ -197,7 +200,7 @@ func (n *Node) handleExpiredAndActivated(height int32) int { // NextUpdate returns the nearest height in the future that the node should // be refreshed due to changes of claims or supports. -func (n Node) NextUpdate() int32 { +func (n Node) NextUpdate(height int32) int32 { ot := param.ActiveParams.OriginalClaimExpirationTime et := param.ActiveParams.ExtendedClaimExpirationTime @@ -212,9 +215,11 @@ func (n Node) NextUpdate() int32 { next := int32(math.MaxInt32) for _, c := range n.Claims { - ea := expiresAt(c) - if ea < next { - next = ea + if height < param.ActiveParams.GrandForkHeight { + es := expiresAt(c) + if es < next { + next = es + } } // if we're not active, we need to go to activeAt unless we're still invisible there if c.Status == Accepted { @@ -229,9 +234,11 @@ func (n Node) NextUpdate() int32 { } for _, s := range n.Supports { - es := expiresAt(s) - if es < next { - next = es + if height < param.ActiveParams.GrandForkHeight { + es := expiresAt(s) + if es < next { + next = es + } } if s.Status == Accepted { min := s.ActiveAt @@ -244,6 +251,10 @@ func (n Node) NextUpdate() int32 { } } + if next == int32(math.MaxInt32) || next <= height { + return 0 + } + return next } diff --git a/claimtrie/param/general.go b/claimtrie/param/general.go index 92ff06fe98..14c6670a95 100644 --- a/claimtrie/param/general.go +++ b/claimtrie/param/general.go @@ -16,6 +16,7 @@ type ClaimTrieParams struct { NormalizedNameForkHeight int32 AllClaimsInMerkleForkHeight int32 + GrandForkHeight int32 } var ( @@ -32,6 +33,7 @@ var ( MaxRemovalWorkaroundHeight: 658300, NormalizedNameForkHeight: 539940, // targeting 21 March 2019}, https://lbry.com/news/hf1903 AllClaimsInMerkleForkHeight: 658309, // targeting 30 Oct 2019}, https://lbry.com/news/hf1910 + GrandForkHeight: 1800000, } TestNet = ClaimTrieParams{ @@ -45,6 +47,7 @@ var ( MaxRemovalWorkaroundHeight: 1, // if you get a hash mismatch, come back to this NormalizedNameForkHeight: 993380, AllClaimsInMerkleForkHeight: 1198559, + GrandForkHeight: 1800000, } Regtest = ClaimTrieParams{ @@ -58,6 +61,7 @@ var ( MaxRemovalWorkaroundHeight: -1, NormalizedNameForkHeight: 250, AllClaimsInMerkleForkHeight: 349, + GrandForkHeight: 850, } ) From 148579f1bb03238d2bedf882b1b63cc51c65c542 Mon Sep 17 00:00:00 2001 From: Brannon King Date: Thu, 12 Aug 2021 11:22:54 -0400 Subject: [PATCH 2/7] eliminate delay workaround post-fork --- claimtrie/node/manager.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/claimtrie/node/manager.go b/claimtrie/node/manager.go index 4048c13fa9..d159a7a5a6 100644 --- a/claimtrie/node/manager.go +++ b/claimtrie/node/manager.go @@ -349,6 +349,10 @@ func hasZeroActiveClaims(n *Node) bool { // aWorkaroundIsNeeded handles bugs that existed in previous versions func (nm *BaseManager) aWorkaroundIsNeeded(n *Node, chg change.Change) bool { + if chg.Height >= param.ActiveParams.GrandForkHeight { + return false + } + if chg.Type == change.SpendClaim || chg.Type == change.SpendSupport { return false } From 7e043917541524b23a64b581a608698996883b18 Mon Sep 17 00:00:00 2001 From: Brannon King Date: Thu, 12 Aug 2021 11:35:25 -0400 Subject: [PATCH 3/7] enforce name standard after fork height --- blockchain/validate.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blockchain/validate.go b/blockchain/validate.go index eaa290b5ae..ba8e916267 100644 --- a/blockchain/validate.go +++ b/blockchain/validate.go @@ -547,7 +547,7 @@ func checkBlockSanity(block *btcutil.Block, powLimit *big.Int, timeSource Median // Do some preliminary checks on each transaction to ensure they are // sane before continuing. for _, tx := range transactions { - err := CheckTransactionSanity(tx, false) + err := CheckTransactionSanity(tx, block.Height() >= param.ActiveParams.GrandForkHeight) if err != nil { return err } From eff775613116e772a42e8789296578b042095b5d Mon Sep 17 00:00:00 2001 From: Brannon King Date: Thu, 12 Aug 2021 12:28:08 -0400 Subject: [PATCH 4/7] ignore empty claims in the hash computation --- claimtrie/claimtrie.go | 4 ++- claimtrie/node/hash_manager.go | 63 ++++++++++++++++++++++++++++++++++ claimtrie/node/manager.go | 2 +- 3 files changed, 67 insertions(+), 2 deletions(-) create mode 100644 claimtrie/node/hash_manager.go diff --git a/claimtrie/claimtrie.go b/claimtrie/claimtrie.go index 1d848e1317..38667bc586 100644 --- a/claimtrie/claimtrie.go +++ b/claimtrie/claimtrie.go @@ -90,7 +90,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 0000000000..4892cac425 --- /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 d159a7a5a6..e246b887c4 100644 --- a/claimtrie/node/manager.go +++ b/claimtrie/node/manager.go @@ -243,7 +243,7 @@ func (nm *BaseManager) IncrementHeightTo(height int32, temporary bool) ([][]byte 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) } From 70d1d18460d30adaa4b2ea2542cb58c719959841 Mon Sep 17 00:00:00 2001 From: Brannon King Date: Tue, 26 Mar 2024 11:33:58 -0400 Subject: [PATCH 5/7] new claim hash function includes bid, seq, name fixed namespace --- claimtrie/claimtrie.go | 3 +- claimtrie/node/hash_manager.go | 56 +++++++++++++++++++++++++++++++--- 2 files changed, 54 insertions(+), 5 deletions(-) diff --git a/claimtrie/claimtrie.go b/claimtrie/claimtrie.go index 38667bc586..7d1bc1276a 100644 --- a/claimtrie/claimtrie.go +++ b/claimtrie/claimtrie.go @@ -283,7 +283,8 @@ func (ct *ClaimTrie) AppendBlock(temporary bool) error { } func (ct *ClaimTrie) updateTrieForHashForkIfNecessary() bool { - if ct.height != param.ActiveParams.AllClaimsInMerkleForkHeight { + if ct.height != param.ActiveParams.AllClaimsInMerkleForkHeight && + ct.height != param.ActiveParams.GrandForkHeight { return false } diff --git a/claimtrie/node/hash_manager.go b/claimtrie/node/hash_manager.go index 4892cac425..12b4113968 100644 --- a/claimtrie/node/hash_manager.go +++ b/claimtrie/node/hash_manager.go @@ -1,9 +1,12 @@ package node import ( - "github.com/btcsuite/btcd/chaincfg/chainhash" - "github.com/lbryio/chain/claimtrie/change" - "github.com/lbryio/chain/claimtrie/param" + "crypto/sha256" + "encoding/binary" + + "github.com/lbryio/lbcd/chaincfg/chainhash" + "github.com/lbryio/lbcd/claimtrie/change" + "github.com/lbryio/lbcd/claimtrie/param" ) type HashV2Manager struct { @@ -50,13 +53,58 @@ func (nm *HashV3Manager) AppendChange(chg change.Change) { nm.Manager.AppendChange(chg) } +func calculateBidSeqNameHash(name []byte, c *Claim, bid, takeover int32) (*chainhash.Hash, error) { + + s := sha256.New() + + s.Write(c.OutPoint.Hash[:]) + + var temp [4]byte + binary.BigEndian.PutUint32(temp[:], c.OutPoint.Index) + s.Write(temp[:]) + + binary.BigEndian.PutUint32(temp[:], uint32(bid)) + s.Write(temp[:]) + + binary.BigEndian.PutUint32(temp[:], uint32(c.Sequence)) + s.Write(temp[:]) + + binary.BigEndian.PutUint32(temp[:], uint32(takeover)) + s.Write(temp[:]) + + s.Write(name) + + var m [sha256.Size]byte + return chainhash.NewHash(s.Sum(m[:0])) +} + +func (nm *HashV3Manager) bidSeqNameHash(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 i, c := range n.Claims { + if c.Status == Activated { + h, _ := calculateBidSeqNameHash(name, c, int32(i), n.TakenOverAt) + claimHashes = append(claimHashes, h) + } + } + if len(claimHashes) > 0 { + return ComputeMerkleRoot(claimHashes), n.NextUpdate(nm.Height()) + } + return nil, n.NextUpdate(nm.Height()) +} + 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.bidSeqNameHash(name) } return nm.Manager.Hash(name) From e9b2cbb321a7629fc037f91e588698252f9926e5 Mon Sep 17 00:00:00 2001 From: Brannon King Date: Tue, 26 Mar 2024 11:36:29 -0400 Subject: [PATCH 6/7] added proof RPC post-merge fixes other part of test post-merge fix --- blockchain/claimtrie.go | 66 +++++++++++++++++ btcjson/claimcmds.go | 37 ++++++++++ claimtrie/claimtrie.go | 73 ++++++++++++++++++- claimtrie/claimtrie_test.go | 63 ++++++++++++++++ claimtrie/merkletrie/merkletrie.go | 4 ++ claimtrie/merkletrie/ramtrie.go | 70 +++++++++++++++--- claimtrie/node/hash_manager.go | 111 ----------------------------- claimtrie/node/hashfork_manager.go | 76 ++++++++++++++++++++ claimtrie/node/hashfunc.go | 56 +++++++++++++++ rpcclaimtrie.go | 65 +++++++++++++++++ 10 files changed, 500 insertions(+), 121 deletions(-) delete mode 100644 claimtrie/node/hash_manager.go diff --git a/blockchain/claimtrie.go b/blockchain/claimtrie.go index f821537ad5..2c3bcf8f15 100644 --- a/blockchain/claimtrie.go +++ b/blockchain/claimtrie.go @@ -3,6 +3,7 @@ package blockchain import ( "bytes" "fmt" + "strings" "github.com/pkg/errors" @@ -181,3 +182,68 @@ func (b *BlockChain) GetClaimsForName(height int32, name string) (string, *node. n.SortClaimsByBid() return string(normalizedName), n, nil } + +func (b *BlockChain) GetProofForName(name, id string, bid, seq int) (chainhash.Hash, int32, *node.Claim, int32, int32, string, []merkletrie.HashSidePair, error) { + // results: block hash, height, claim, bid, takeover, name, pairs, err + + b.chainLock.RLock() + defer b.chainLock.RUnlock() + + tip := b.bestChain.Tip() + + normalizedName := normalization.NormalizeIfNecessary([]byte(name), tip.height) + + if tip.height < param.ActiveParams.GrandForkHeight { + err := errors.Errorf("Unable to generate proofs for claims before height %d", + param.ActiveParams.GrandForkHeight) + return tip.hash, tip.height, nil, 0, 0, string(normalizedName), nil, err + } + + n, err := b.claimTrie.NodeAt(tip.height, normalizedName) + if n == nil && err == nil { + err = errors.Errorf("Unable to locate a claim with name %s at height %d", normalizedName, tip.height) + } + if err != nil { + return tip.hash, tip.height, nil, 0, 0, string(normalizedName), nil, err + } + + // now find the desired claim + n.SortClaimsByBid() + var claim *node.Claim + for i, c := range n.Claims { + if c.Status != node.Activated { + continue + } + if bid >= 0 && i == bid { + claim = c + bid = i + break + } + if seq >= 0 && int(c.Sequence) == seq { + claim = c + bid = i + break + } + if len(id) > 0 && strings.HasPrefix(c.ClaimID.String(), id) { + claim = c + bid = i + break + } + } + if claim == nil { + if bid >= 0 { + err = errors.Errorf("Unable to locate a claim named %s with bid %d at height %d", normalizedName, bid, tip.height) + } + if seq >= 0 { + err = errors.Errorf("Unable to locate a claim named %s with sequence %d at height %d", normalizedName, seq, tip.height) + } + if len(id) > 0 { + err = errors.Errorf("Unable to locate a claim named %s with ID %s at height %d", normalizedName, id, tip.height) + } + return tip.hash, tip.height, nil, 0, 0, string(normalizedName), nil, err + } + + pairs := b.claimTrie.MerklePath(normalizedName, n, bid) + + return tip.hash, tip.height, claim, int32(bid), n.TakenOverAt, string(normalizedName), pairs, nil +} diff --git a/btcjson/claimcmds.go b/btcjson/claimcmds.go index 8f50fc0c70..fd1b0b867a 100644 --- a/btcjson/claimcmds.go +++ b/btcjson/claimcmds.go @@ -10,6 +10,10 @@ func init() { MustRegisterCmd("getclaimsfornamebybid", (*GetClaimsForNameByBidCmd)(nil), flags) MustRegisterCmd("getclaimsfornamebyseq", (*GetClaimsForNameBySeqCmd)(nil), flags) MustRegisterCmd("normalize", (*GetNormalizedCmd)(nil), flags) + + MustRegisterCmd("getprooffornamebyid", (*GetProofForNameByIDCmd)(nil), flags) + MustRegisterCmd("getprooffornamebybid", (*GetProofForNameByBidCmd)(nil), flags) + MustRegisterCmd("getprooffornamebyseq", (*GetProofForNameBySeqCmd)(nil), flags) } // optional inputs are required to be pointers, but they support things like `jsonrpcdefault:"false"` @@ -95,3 +99,36 @@ type GetNormalizedCmd struct { type GetNormalizedResult struct { NormalizedName string `json:"normalizedname"` } + +type GetProofForNameByIDCmd struct { + Name string `json:"name"` + PartialClaimID string `json:"partialclaimid"` +} + +type GetProofForNameByBidCmd struct { + Name string `json:"name"` + Bid int `json:"bid"` +} + +type GetProofForNameBySeqCmd struct { + Name string `json:"name"` + Sequence int `json:"sequence"` +} + +type ProofPairResult struct { + Right bool `json:"right"` + Hash string `json:"hash"` +} + +type ProofResult struct { // should we include the claim trie hash? + BlockHash string `json:"blockhash"` + BlockHeight int32 `json:"blockheight"` + NormalizedName string `json:"normalizedname"` + ClaimID string `json:"claimid"` + TXID string `json:"txid"` + N uint32 `json:"n"` + Bid int32 `json:"bid"` + Sequence int32 `json:"sequence"` + Takeover int32 `json:"takeover"` + Pairs []ProofPairResult `json:"pairs"` +} diff --git a/claimtrie/claimtrie.go b/claimtrie/claimtrie.go index 7d1bc1276a..21117e035b 100644 --- a/claimtrie/claimtrie.go +++ b/claimtrie/claimtrie.go @@ -306,7 +306,7 @@ func removeDuplicates(names [][]byte) [][]byte { // this might be too expensive; return names } -// ResetHeight resets the ClaimTrie to a previous known height.. +// ResetHeight resets the ClaimTrie to a previous known height. func (ct *ClaimTrie) ResetHeight(height int32) error { names := make([][]byte, 0) @@ -323,6 +323,9 @@ func (ct *ClaimTrie) ResetHeight(height int32) error { } passedHashFork := ct.height >= param.ActiveParams.AllClaimsInMerkleForkHeight && height < param.ActiveParams.AllClaimsInMerkleForkHeight + if !passedHashFork { + passedHashFork = ct.height >= param.ActiveParams.GrandForkHeight && height < param.ActiveParams.GrandForkHeight + } hash, err := ct.blockRepo.Get(height) if err != nil { return err @@ -454,3 +457,71 @@ func interruptRequested(interrupted <-chan struct{}) bool { return false } + +func (ct *ClaimTrie) makeNameHashNext(names [][]byte, all bool, interrupt <-chan struct{}) chan NameHashNext { + inputs := make(chan []byte, 512) + outputs := make(chan NameHashNext, 512) + + var wg sync.WaitGroup + hashComputationWorker := func() { + for name := range inputs { + hash, next := ct.nodeManager.Hash(name) + outputs <- NameHashNext{name, hash, next} + } + wg.Done() + } + + threads := int(0.8 * float32(runtime.NumCPU())) + if threads < 1 { + threads = 1 + } + for threads > 0 { + threads-- + wg.Add(1) + go hashComputationWorker() + } + go func() { + if all { + ct.nodeManager.IterateNames(func(name []byte) bool { + if interruptRequested(interrupt) { + return false + } + clone := make([]byte, len(name)) + copy(clone, name) // iteration name buffer is reused on future loops + inputs <- clone + return true + }) + } else { + for _, name := range names { + if interruptRequested(interrupt) { + break + } + inputs <- name + } + } + close(inputs) + }() + go func() { + wg.Wait() + close(outputs) + }() + return outputs +} + +func (ct *ClaimTrie) MerklePath(name []byte, n *node.Node, bid int) []merkletrie.HashSidePair { + pairs := ct.merkleTrie.MerklePath(name) + // TODO: organize this code better + // this is the 2nd half of the above merkle tree computation + // it's done like this so we don't have to create the Node object multiple times + claimHashes := node.ComputeClaimHashes(name, n) + partials := node.ComputeMerklePath(claimHashes, bid) + for i := len(partials) - 1; i >= 0; i-- { + pairs = append(pairs, merkletrie.HashSidePair{Right: ((bid >> i) & 1) > 0, Hash: partials[i]}) + } + + // reverse the list order: + for i, j := 0, len(pairs)-1; i < j; i, j = i+1, j-1 { + pairs[i], pairs[j] = pairs[j], pairs[i] + } + return pairs +} diff --git a/claimtrie/claimtrie_test.go b/claimtrie/claimtrie_test.go index 61194f1ad8..53beceea7f 100644 --- a/claimtrie/claimtrie_test.go +++ b/claimtrie/claimtrie_test.go @@ -1025,3 +1025,66 @@ func TestBlock884431(t *testing.T) { r.NoError(err) r.Equal(o11.String(), n.BestClaim.OutPoint.String()) } + +func TestMerklePath(t *testing.T) { + r := require.New(t) + setup(t) + param.ActiveParams.ActiveDelayFactor = 1 + param.ActiveParams.NormalizedNameForkHeight = 5 + param.ActiveParams.AllClaimsInMerkleForkHeight = 6 + param.ActiveParams.GrandForkHeight = 7 + + ct, err := New(cfg) + r.NoError(err) + r.NotNil(ct) + defer ct.Close() + + hash := chainhash.HashH([]byte{1, 2, 3}) + o1 := wire.OutPoint{Hash: hash, Index: 1} + o2 := wire.OutPoint{Hash: hash, Index: 2} + o3 := wire.OutPoint{Hash: hash, Index: 3} + + err = ct.AddClaim([]byte("test"), o1, change.NewClaimID(o1), 1) + r.NoError(err) + + err = ct.AddClaim([]byte("test"), o2, change.NewClaimID(o2), 2) + r.NoError(err) + + err = ct.AddClaim([]byte("tester"), o3, change.NewClaimID(o3), 1) + r.NoError(err) + + for i := 0; i < 10; i++ { + err = ct.AppendBlock() + r.NoError(err) + } + + n, err := ct.NodeAt(ct.height, []byte("test")) + r.NoError(err) + pairs := ct.MerklePath([]byte("test"), n, 0) + claimHash, err := node.ComputeBidSeqNameHash([]byte("test"), n.Claims[0], 0, n.TakenOverAt) + r.NoError(err) + validatePairs(r, pairs, ct.MerkleHash(), claimHash) + + pairs = ct.MerklePath([]byte("test"), n, 1) + claimHash, err = node.ComputeBidSeqNameHash([]byte("test"), n.Claims[1], 1, n.TakenOverAt) + r.NoError(err) + validatePairs(r, pairs, ct.MerkleHash(), claimHash) + + n, err = ct.NodeAt(ct.height, []byte("tester")) + r.NoError(err) + pairs = ct.MerklePath([]byte("tester"), n, 0) + claimHash, err = node.ComputeBidSeqNameHash([]byte("tester"), n.Claims[0], 0, n.TakenOverAt) + r.NoError(err) + validatePairs(r, pairs, ct.MerkleHash(), claimHash) +} + +func validatePairs(r *require.Assertions, pairs []merkletrie.HashSidePair, target *chainhash.Hash, claimHash *chainhash.Hash) { + for i := range pairs { + if pairs[i].Right { + claimHash = node.HashMerkleBranches(pairs[i].Hash, claimHash) + } else { + claimHash = node.HashMerkleBranches(claimHash, pairs[i].Hash) + } + } + r.True(claimHash.IsEqual(target)) +} diff --git a/claimtrie/merkletrie/merkletrie.go b/claimtrie/merkletrie/merkletrie.go index 3bc525fe0a..e92e2d4337 100644 --- a/claimtrie/merkletrie/merkletrie.go +++ b/claimtrie/merkletrie/merkletrie.go @@ -253,3 +253,7 @@ func (t *PersistentTrie) Dump(s string) { func (t *PersistentTrie) Flush() error { return t.repo.Flush() } + +func (t *PersistentTrie) MerklePath(name []byte) []HashSidePair { + panic("MerklePath not implemented in PersistentTrie") +} diff --git a/claimtrie/merkletrie/ramtrie.go b/claimtrie/merkletrie/ramtrie.go index 7b4266556e..293661a4a3 100644 --- a/claimtrie/merkletrie/ramtrie.go +++ b/claimtrie/merkletrie/ramtrie.go @@ -16,6 +16,7 @@ type MerkleTrie interface { MerkleHash() *chainhash.Hash MerkleHashAllClaims() *chainhash.Hash Flush() error + MerklePath(name []byte) []HashSidePair } type RamTrie struct { @@ -111,29 +112,80 @@ func (rt *RamTrie) merkleHashAllClaims(v *collapsedVertex) *chainhash.Hash { return v.merkleHash } - childHashes := make([]*chainhash.Hash, 0, len(v.children)) - for _, ch := range v.children { - h := rt.merkleHashAllClaims(ch) - childHashes = append(childHashes, h) - } + childHash, hasChildren := rt.computeChildHash(v) claimHash := NoClaimsHash if v.claimHash != nil { claimHash = v.claimHash - } else if len(childHashes) == 0 { + } else if !hasChildren { return nil } + v.merkleHash = node.HashMerkleBranches(childHash, claimHash) + return v.merkleHash +} + +func (rt *RamTrie) computeChildHash(v *collapsedVertex) (*chainhash.Hash, bool) { + childHashes := make([]*chainhash.Hash, 0, len(v.children)) + for _, ch := range v.children { + h := rt.merkleHashAllClaims(ch) + childHashes = append(childHashes, h) + } childHash := NoChildrenHash if len(childHashes) > 0 { // this shouldn't be referencing node; where else can we put this merkle root func? childHash = node.ComputeMerkleRoot(childHashes) } - - v.merkleHash = node.HashMerkleBranches(childHash, claimHash) - return v.merkleHash + return childHash, len(childHashes) > 0 } func (rt *RamTrie) Flush() error { return nil } + +type HashSidePair struct { + Right bool + Hash *chainhash.Hash +} + +func (rt *RamTrie) MerklePath(name []byte) []HashSidePair { + + // algorithm: + // for each node in the path to key: + // get all the childHashes for that node and the index of our path + // get all the claimHashes for that node as well + // if we're at the end of the path: + // push(true, root(childHashes)) + // push all of merklePath(claimHashes, bid) + // else + // push(false, root(claimHashes) + // push all of merklePath(childHashes, child index) + + var results []HashSidePair + + indexes, path := rt.FindPath(name) + for i := 0; i < len(indexes); i++ { + if i == len(indexes)-1 { + childHash, _ := rt.computeChildHash(path[i]) + results = append(results, HashSidePair{Right: true, Hash: childHash}) + // letting the caller append the claim hashes at present (needs better code organization) + } else { + ch := path[i].claimHash + if ch == nil { + ch = NoClaimsHash + } + results = append(results, HashSidePair{Right: false, Hash: ch}) + childHashes := make([]*chainhash.Hash, 0, len(path[i].children)) + for j := range path[i].children { + childHashes = append(childHashes, path[i].children[j].merkleHash) + } + if len(childHashes) > 0 { + partials := node.ComputeMerklePath(childHashes, indexes[i+1]) + for i := len(partials) - 1; i >= 0; i-- { + results = append(results, HashSidePair{Right: ((indexes[i+1] >> i) & 1) > 0, Hash: partials[i]}) + } + } + } + } + return results +} diff --git a/claimtrie/node/hash_manager.go b/claimtrie/node/hash_manager.go deleted file mode 100644 index 12b4113968..0000000000 --- a/claimtrie/node/hash_manager.go +++ /dev/null @@ -1,111 +0,0 @@ -package node - -import ( - "crypto/sha256" - "encoding/binary" - - "github.com/lbryio/lbcd/chaincfg/chainhash" - "github.com/lbryio/lbcd/claimtrie/change" - "github.com/lbryio/lbcd/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 calculateBidSeqNameHash(name []byte, c *Claim, bid, takeover int32) (*chainhash.Hash, error) { - - s := sha256.New() - - s.Write(c.OutPoint.Hash[:]) - - var temp [4]byte - binary.BigEndian.PutUint32(temp[:], c.OutPoint.Index) - s.Write(temp[:]) - - binary.BigEndian.PutUint32(temp[:], uint32(bid)) - s.Write(temp[:]) - - binary.BigEndian.PutUint32(temp[:], uint32(c.Sequence)) - s.Write(temp[:]) - - binary.BigEndian.PutUint32(temp[:], uint32(takeover)) - s.Write(temp[:]) - - s.Write(name) - - var m [sha256.Size]byte - return chainhash.NewHash(s.Sum(m[:0])) -} - -func (nm *HashV3Manager) bidSeqNameHash(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 i, c := range n.Claims { - if c.Status == Activated { - h, _ := calculateBidSeqNameHash(name, c, int32(i), n.TakenOverAt) - claimHashes = append(claimHashes, h) - } - } - if len(claimHashes) > 0 { - return ComputeMerkleRoot(claimHashes), n.NextUpdate(nm.Height()) - } - return nil, n.NextUpdate(nm.Height()) -} - -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.bidSeqNameHash(name) - } - - return nm.Manager.Hash(name) -} diff --git a/claimtrie/node/hashfork_manager.go b/claimtrie/node/hashfork_manager.go index b25c631c9b..840b5202e5 100644 --- a/claimtrie/node/hashfork_manager.go +++ b/claimtrie/node/hashfork_manager.go @@ -1,6 +1,9 @@ package node import ( + "crypto/sha256" + "encoding/binary" + "github.com/lbryio/lbcd/chaincfg/chainhash" "github.com/lbryio/lbcd/claimtrie/param" ) @@ -9,6 +12,10 @@ type HashV2Manager struct { Manager } +type HashV3Manager struct { + Manager +} + func (nm *HashV2Manager) computeClaimHashes(name []byte) (*chainhash.Hash, int32) { n, err := nm.NodeAt(nm.Height(), name) @@ -37,3 +44,72 @@ func (nm *HashV2Manager) Hash(name []byte) (*chainhash.Hash, int32) { 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 ComputeBidSeqNameHash(name []byte, c *Claim, bid, takeover int32) (*chainhash.Hash, error) { + + s := sha256.New() + + s.Write(c.OutPoint.Hash[:]) + + var temp [4]byte + binary.BigEndian.PutUint32(temp[:], c.OutPoint.Index) + s.Write(temp[:]) + + binary.BigEndian.PutUint32(temp[:], uint32(bid)) + s.Write(temp[:]) + + binary.BigEndian.PutUint32(temp[:], uint32(c.Sequence)) + s.Write(temp[:]) + + binary.BigEndian.PutUint32(temp[:], uint32(takeover)) + s.Write(temp[:]) + + s.Write(name) + + var m [sha256.Size]byte + return chainhash.NewHash(s.Sum(m[:0])) +} + +func (nm *HashV3Manager) bidSeqNameHash(name []byte) (*chainhash.Hash, int32) { + n, err := nm.NodeAt(nm.Height(), name) + if err != nil || n == nil { + return nil, 0 + } + + claimHashes := ComputeClaimHashes(name, n) + if len(claimHashes) > 0 { + return ComputeMerkleRoot(claimHashes), n.NextUpdate(nm.Height()) + } + return nil, n.NextUpdate(nm.Height()) +} + +func ComputeClaimHashes(name []byte, n *Node) []*chainhash.Hash { + n.SortClaimsByBid() + claimHashes := make([]*chainhash.Hash, 0, len(n.Claims)) + for i, c := range n.Claims { + if c.Status == Activated { + h, _ := ComputeBidSeqNameHash(name, c, int32(i), n.TakenOverAt) + claimHashes = append(claimHashes, h) + } + } + return claimHashes +} + +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.bidSeqNameHash(name) + } + + return nm.Manager.Hash(name) +} diff --git a/claimtrie/node/hashfunc.go b/claimtrie/node/hashfunc.go index deec78bbf2..0fbeaf4567 100644 --- a/claimtrie/node/hashfunc.go +++ b/claimtrie/node/hashfunc.go @@ -55,3 +55,59 @@ func calculateNodeHash(op wire.OutPoint, takeover int32) *chainhash.Hash { return &hh } + +func ComputeMerklePath(hashes []*chainhash.Hash, idx int) []*chainhash.Hash { + count := 0 + matchlevel := -1 + matchh := false + var h *chainhash.Hash + var res []*chainhash.Hash + var inner [32]*chainhash.Hash // old code had 32; dunno if it's big enough for all scenarios + + iterateInner := func(level int) int { + for ; (count & (1 << level)) == 0; level++ { + ihash := inner[level] + if matchh { + res = append(res, ihash) + } else if matchlevel == level { + res = append(res, h) + matchh = true + } + h = HashMerkleBranches(ihash, h) + } + return level + } + + for count < len(hashes) { + h = hashes[count] + matchh = count == idx + count++ + level := iterateInner(0) + // Store the resulting hash at inner position level. + inner[level] = h + if matchh { + matchlevel = level + } + } + + level := 0 + for (count & (1 << level)) == 0 { + level++ + } + + h = inner[level] + matchh = matchlevel == level + + for count != (1 << level) { + // If we reach this point, h is an inner value that is not the top. + if matchh { + res = append(res, h) + } + h = HashMerkleBranches(h, h) + // Increment count to the value it would have if two entries at this + count += 1 << level + level++ + level = iterateInner(level) + } + return res +} diff --git a/rpcclaimtrie.go b/rpcclaimtrie.go index 11706920ea..92ad7fe849 100644 --- a/rpcclaimtrie.go +++ b/rpcclaimtrie.go @@ -22,6 +22,10 @@ var claimtrieHandlers = map[string]commandHandler{ "getclaimsfornamebybid": handleGetClaimsForNameByBid, "getclaimsfornamebyseq": handleGetClaimsForNameBySeq, "normalize": handleGetNormalized, + + "getprooffornamebyid": handleGetProofForNameByID, + "getprooffornamebybid": handleGetProofForNameByBid, + "getprooffornamebyseq": handleGetProofForNameBySeq, } func handleGetChangesInBlock(s *rpcServer, cmd interface{}, _ <-chan struct{}) (interface{}, error) { @@ -350,3 +354,64 @@ func handleGetNormalized(_ *rpcServer, cmd interface{}, _ <-chan struct{}) (inte } return r, nil } + +func handleGetProofForNameByID(s *rpcServer, cmd interface{}, _ <-chan struct{}) (interface{}, error) { + + c := cmd.(*btcjson.GetProofForNameByIDCmd) + return getProof(s, c.Name, c.PartialClaimID, -1, -1) +} + +func handleGetProofForNameByBid(s *rpcServer, cmd interface{}, _ <-chan struct{}) (interface{}, error) { + + c := cmd.(*btcjson.GetProofForNameByBidCmd) + return getProof(s, c.Name, "", c.Bid, -1) +} + +func handleGetProofForNameBySeq(s *rpcServer, cmd interface{}, _ <-chan struct{}) (interface{}, error) { + + c := cmd.(*btcjson.GetProofForNameBySeqCmd) + return getProof(s, c.Name, "", -1, c.Sequence) +} + +func getProof(s *rpcServer, name, id string, bid, seq int) (interface{}, error) { + + if !s.cfg.Chain.IsCurrent() { + return nil, &btcjson.RPCError{ + Code: btcjson.ErrRPCClientInInitialDownload, + Message: "Unable to query the chain tip during initial download", + } + } + + if len(name) == 0 { + return nil, &btcjson.RPCError{ + Code: btcjson.ErrRPCInvalidParameter, + Message: "name is required and cannot be empty", + } + } + + bh, h, c, b, t, n, pairs, err := s.cfg.Chain.GetProofForName(name, id, bid, seq) + if err != nil { + return nil, &btcjson.RPCError{ + Code: btcjson.ErrRPCMisc, + Message: "Message: " + err.Error(), + } + } + + results := make([]btcjson.ProofPairResult, 0, len(pairs)) + for i := 0; i < len(pairs); i++ { + results = append(results, btcjson.ProofPairResult{Right: pairs[i].Right, Hash: pairs[i].Hash.String()}) + } + + return btcjson.ProofResult{ + BlockHash: bh.String(), + BlockHeight: h, + NormalizedName: n, + ClaimID: c.ClaimID.String(), + TXID: c.OutPoint.Hash.String(), + N: c.OutPoint.Index, + Bid: b, + Sequence: c.Sequence, + Takeover: t, + Pairs: results, + }, nil +} From 5a99dcfe81edcb31acf9755d47ff8e34fe6b5b7a Mon Sep 17 00:00:00 2001 From: Brannon King Date: Tue, 26 Mar 2024 11:55:37 -0400 Subject: [PATCH 7/7] post-rebase fixes post-rebase fixes 2 --- addrmgr/addrmanager_internal_test.go | 5 +++ blockchain/claimtrie.go | 3 ++ blockchain/validate.go | 1 + claimtrie/claimtrie.go | 50 ---------------------------- claimtrie/claimtrie_test.go | 3 +- claimtrie/node/hashfork_manager.go | 1 + 6 files changed, 12 insertions(+), 51 deletions(-) diff --git a/addrmgr/addrmanager_internal_test.go b/addrmgr/addrmanager_internal_test.go index b2f5f3d140..451ad18ab5 100644 --- a/addrmgr/addrmanager_internal_test.go +++ b/addrmgr/addrmanager_internal_test.go @@ -99,7 +99,12 @@ func TestAddrManagerSerialization(t *testing.T) { expectedAddrs := make(map[string]*wire.NetAddress, numAddrs) for i := 0; i < numAddrs; i++ { addr := randAddr(t) + cnt := len(expectedAddrs) expectedAddrs[NetAddressKey(addr)] = addr + if len(expectedAddrs) == cnt { + i-- // accidentally generated a duplicate + continue + } addrMgr.AddAddress(addr, randAddr(t)) } diff --git a/blockchain/claimtrie.go b/blockchain/claimtrie.go index 2c3bcf8f15..a37b78232d 100644 --- a/blockchain/claimtrie.go +++ b/blockchain/claimtrie.go @@ -7,14 +7,17 @@ import ( "github.com/pkg/errors" + "github.com/lbryio/lbcd/chaincfg/chainhash" "github.com/lbryio/lbcd/txscript" "github.com/lbryio/lbcd/wire" btcutil "github.com/lbryio/lbcutil" "github.com/lbryio/lbcd/claimtrie" "github.com/lbryio/lbcd/claimtrie/change" + "github.com/lbryio/lbcd/claimtrie/merkletrie" "github.com/lbryio/lbcd/claimtrie/node" "github.com/lbryio/lbcd/claimtrie/normalization" + "github.com/lbryio/lbcd/claimtrie/param" ) func (b *BlockChain) SetClaimtrieHeader(block *btcutil.Block, view *UtxoViewpoint) error { diff --git a/blockchain/validate.go b/blockchain/validate.go index ba8e916267..9aae5244be 100644 --- a/blockchain/validate.go +++ b/blockchain/validate.go @@ -13,6 +13,7 @@ import ( "github.com/lbryio/lbcd/chaincfg" "github.com/lbryio/lbcd/chaincfg/chainhash" + "github.com/lbryio/lbcd/claimtrie/param" "github.com/lbryio/lbcd/txscript" "github.com/lbryio/lbcd/wire" btcutil "github.com/lbryio/lbcutil" diff --git a/claimtrie/claimtrie.go b/claimtrie/claimtrie.go index 21117e035b..3ad4a22657 100644 --- a/claimtrie/claimtrie.go +++ b/claimtrie/claimtrie.go @@ -458,56 +458,6 @@ func interruptRequested(interrupted <-chan struct{}) bool { return false } -func (ct *ClaimTrie) makeNameHashNext(names [][]byte, all bool, interrupt <-chan struct{}) chan NameHashNext { - inputs := make(chan []byte, 512) - outputs := make(chan NameHashNext, 512) - - var wg sync.WaitGroup - hashComputationWorker := func() { - for name := range inputs { - hash, next := ct.nodeManager.Hash(name) - outputs <- NameHashNext{name, hash, next} - } - wg.Done() - } - - threads := int(0.8 * float32(runtime.NumCPU())) - if threads < 1 { - threads = 1 - } - for threads > 0 { - threads-- - wg.Add(1) - go hashComputationWorker() - } - go func() { - if all { - ct.nodeManager.IterateNames(func(name []byte) bool { - if interruptRequested(interrupt) { - return false - } - clone := make([]byte, len(name)) - copy(clone, name) // iteration name buffer is reused on future loops - inputs <- clone - return true - }) - } else { - for _, name := range names { - if interruptRequested(interrupt) { - break - } - inputs <- name - } - } - close(inputs) - }() - go func() { - wg.Wait() - close(outputs) - }() - return outputs -} - func (ct *ClaimTrie) MerklePath(name []byte, n *node.Node, bid int) []merkletrie.HashSidePair { pairs := ct.merkleTrie.MerklePath(name) // TODO: organize this code better diff --git a/claimtrie/claimtrie_test.go b/claimtrie/claimtrie_test.go index 53beceea7f..a251a4b58a 100644 --- a/claimtrie/claimtrie_test.go +++ b/claimtrie/claimtrie_test.go @@ -8,6 +8,7 @@ import ( "github.com/lbryio/lbcd/claimtrie/change" "github.com/lbryio/lbcd/claimtrie/config" "github.com/lbryio/lbcd/claimtrie/merkletrie" + "github.com/lbryio/lbcd/claimtrie/node" "github.com/lbryio/lbcd/claimtrie/param" "github.com/lbryio/lbcd/chaincfg/chainhash" @@ -1054,7 +1055,7 @@ func TestMerklePath(t *testing.T) { r.NoError(err) for i := 0; i < 10; i++ { - err = ct.AppendBlock() + err = ct.AppendBlock(false) r.NoError(err) } diff --git a/claimtrie/node/hashfork_manager.go b/claimtrie/node/hashfork_manager.go index 840b5202e5..31477bba53 100644 --- a/claimtrie/node/hashfork_manager.go +++ b/claimtrie/node/hashfork_manager.go @@ -5,6 +5,7 @@ import ( "encoding/binary" "github.com/lbryio/lbcd/chaincfg/chainhash" + "github.com/lbryio/lbcd/claimtrie/change" "github.com/lbryio/lbcd/claimtrie/param" )