github.com/lbryio/lbcd@v0.22.119/claimtrie/node/normalizing_manager.go (about) 1 package node 2 3 import ( 4 "bytes" 5 6 "github.com/lbryio/lbcd/claimtrie/change" 7 "github.com/lbryio/lbcd/claimtrie/normalization" 8 "github.com/lbryio/lbcd/claimtrie/param" 9 ) 10 11 type NormalizingManager struct { // implements Manager 12 Manager 13 normalizedAt int32 14 } 15 16 func NewNormalizingManager(baseManager Manager) Manager { 17 log.Info(normalization.NormalizeTitle) 18 return &NormalizingManager{ 19 Manager: baseManager, 20 normalizedAt: -1, 21 } 22 } 23 24 func (nm *NormalizingManager) AppendChange(chg change.Change) { 25 chg.Name = normalization.NormalizeIfNecessary(chg.Name, chg.Height) 26 nm.Manager.AppendChange(chg) 27 } 28 29 func (nm *NormalizingManager) IncrementHeightTo(height int32, temporary bool) ([][]byte, error) { 30 nm.addNormalizationForkChangesIfNecessary(height) 31 return nm.Manager.IncrementHeightTo(height, temporary) 32 } 33 34 func (nm *NormalizingManager) DecrementHeightTo(affectedNames [][]byte, height int32) ([][]byte, error) { 35 if nm.normalizedAt > height { 36 nm.normalizedAt = -1 37 nm.ClearCache() 38 } 39 return nm.Manager.DecrementHeightTo(affectedNames, height) 40 } 41 42 func (nm *NormalizingManager) addNormalizationForkChangesIfNecessary(height int32) { 43 44 if nm.Manager.Height()+1 != height { 45 // initialization phase 46 if height >= param.ActiveParams.NormalizedNameForkHeight { 47 nm.normalizedAt = param.ActiveParams.NormalizedNameForkHeight // eh, we don't really know that it happened there 48 } 49 } 50 51 if nm.normalizedAt >= 0 || height != param.ActiveParams.NormalizedNameForkHeight { 52 return 53 } 54 nm.normalizedAt = height 55 log.Info("Generating necessary changes for the normalization fork...") 56 57 // the original code had an unfortunate bug where many unnecessary takeovers 58 // were triggered at the normalization fork 59 predicate := func(name []byte) bool { 60 norm := normalization.Normalize(name) 61 eq := bytes.Equal(name, norm) 62 if eq { 63 return true 64 } 65 66 clone := make([]byte, len(name)) 67 copy(clone, name) // iteration name buffer is reused on future loops 68 69 // by loading changes for norm here, you can determine if there will be a conflict 70 71 n, err := nm.Manager.NodeAt(nm.Manager.Height(), clone) 72 if err != nil || n == nil { 73 return true 74 } 75 for _, c := range n.Claims { 76 nm.Manager.AppendChange(change.Change{ 77 Type: change.AddClaim, 78 Name: norm, 79 Height: c.AcceptedAt, 80 OutPoint: c.OutPoint, 81 ClaimID: c.ClaimID, 82 Amount: c.Amount, 83 ActiveHeight: c.ActiveAt, // necessary to match the old hash 84 VisibleHeight: height, // necessary to match the old hash; it would have been much better without 85 }) 86 nm.Manager.AppendChange(change.Change{ 87 Type: change.SpendClaim, 88 Name: clone, 89 Height: height, 90 OutPoint: c.OutPoint, 91 }) 92 } 93 for _, c := range n.Supports { 94 nm.Manager.AppendChange(change.Change{ 95 Type: change.AddSupport, 96 Name: norm, 97 Height: c.AcceptedAt, 98 OutPoint: c.OutPoint, 99 ClaimID: c.ClaimID, 100 Amount: c.Amount, 101 ActiveHeight: c.ActiveAt, 102 VisibleHeight: height, 103 }) 104 nm.Manager.AppendChange(change.Change{ 105 Type: change.SpendSupport, 106 Name: clone, 107 Height: height, 108 OutPoint: c.OutPoint, 109 }) 110 } 111 112 return true 113 } 114 115 nm.Manager.ClearCache() 116 nm.Manager.IterateNames(predicate) 117 }