github.com/braveheart12/insolar-09-08-19@v0.8.7/network/nodenetwork/unsync_list.go (about) 1 /* 2 * The Clear BSD License 3 * 4 * Copyright (c) 2019 Insolar Technologies 5 * 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without modification, are permitted (subject to the limitations in the disclaimer below) provided that the following conditions are met: 9 * 10 * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 11 * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 12 * Neither the name of Insolar Technologies nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 13 * 14 * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 15 * 16 */ 17 18 package nodenetwork 19 20 import ( 21 "sort" 22 23 consensus "github.com/insolar/insolar/consensus/packets" 24 "github.com/insolar/insolar/core" 25 "github.com/insolar/insolar/network" 26 "github.com/pkg/errors" 27 ) 28 29 func copyActiveNodes(m map[core.RecordRef]core.Node) map[core.RecordRef]core.Node { 30 result := make(map[core.RecordRef]core.Node, len(m)) 31 for k, v := range m { 32 v.(MutableNode).ChangeState() 33 result[k] = v 34 } 35 return result 36 } 37 38 type unsyncList struct { 39 length int 40 origin core.Node 41 activeNodes map[core.RecordRef]core.Node 42 claims map[core.RecordRef][]consensus.ReferendumClaim 43 refToIndex map[core.RecordRef]int 44 proofs map[core.RecordRef]*consensus.NodePulseProof 45 ghs map[core.RecordRef]consensus.GlobuleHashSignature 46 indexToRef map[int]core.RecordRef 47 cache []byte 48 } 49 50 func (ul *unsyncList) GetGlobuleHashSignature(ref core.RecordRef) (consensus.GlobuleHashSignature, bool) { 51 ghs, ok := ul.ghs[ref] 52 return ghs, ok 53 } 54 55 func (ul *unsyncList) SetGlobuleHashSignature(ref core.RecordRef, ghs consensus.GlobuleHashSignature) { 56 ul.ghs[ref] = ghs 57 } 58 59 func (ul *unsyncList) RemoveNode(nodeID core.RecordRef) { 60 delete(ul.activeNodes, nodeID) 61 delete(ul.claims, nodeID) 62 delete(ul.proofs, nodeID) 63 delete(ul.ghs, nodeID) 64 } 65 66 func (ul *unsyncList) ApproveSync(sync []core.RecordRef) { 67 prevActive := make([]core.RecordRef, 0, len(ul.activeNodes)) 68 for nodeID := range ul.activeNodes { 69 prevActive = append(prevActive, nodeID) 70 } 71 diff := removeFromList(prevActive, sync) 72 for _, node := range diff { 73 ul.removeNode(node) 74 } 75 } 76 77 func (ul *unsyncList) AddNode(node core.Node, bitsetIndex uint16) { 78 ul.addNode(node, int(bitsetIndex)) 79 } 80 81 func (ul *unsyncList) GetClaims(nodeID core.RecordRef) []consensus.ReferendumClaim { 82 return ul.claims[nodeID] 83 } 84 85 func (ul *unsyncList) AddProof(nodeID core.RecordRef, proof *consensus.NodePulseProof) { 86 ul.proofs[nodeID] = proof 87 } 88 89 func (ul *unsyncList) GetProof(nodeID core.RecordRef) *consensus.NodePulseProof { 90 return ul.proofs[nodeID] 91 } 92 93 func newUnsyncList(origin core.Node, activeNodesSorted []core.Node, length int) *unsyncList { 94 result := &unsyncList{ 95 length: length, 96 origin: origin, 97 indexToRef: make(map[int]core.RecordRef, len(activeNodesSorted)), 98 refToIndex: make(map[core.RecordRef]int, len(activeNodesSorted)), 99 activeNodes: make(map[core.RecordRef]core.Node, len(activeNodesSorted)), 100 } 101 for i, node := range activeNodesSorted { 102 result.addNode(node, i) 103 } 104 result.proofs = make(map[core.RecordRef]*consensus.NodePulseProof) 105 result.claims = make(map[core.RecordRef][]consensus.ReferendumClaim) 106 result.ghs = make(map[core.RecordRef]consensus.GlobuleHashSignature) 107 108 return result 109 } 110 111 func (ul *unsyncList) addNodes(nodes []core.Node) { 112 sort.Slice(nodes, func(i, j int) bool { 113 return nodes[i].ID().Compare(nodes[j].ID()) < 0 114 }) 115 116 for index, node := range nodes { 117 ul.addNode(node, index) 118 } 119 } 120 121 func (ul *unsyncList) addNode(node core.Node, index int) { 122 ul.indexToRef[index] = node.ID() 123 ul.refToIndex[node.ID()] = index 124 ul.activeNodes[node.ID()] = node 125 } 126 127 func (ul *unsyncList) removeNode(nodeID core.RecordRef) { 128 delete(ul.activeNodes, nodeID) 129 delete(ul.claims, nodeID) 130 delete(ul.proofs, nodeID) 131 delete(ul.ghs, nodeID) 132 i, ok := ul.refToIndex[nodeID] 133 if ok { 134 delete(ul.indexToRef, i) 135 } 136 delete(ul.refToIndex, nodeID) 137 ul.cache = nil 138 } 139 140 func (ul *unsyncList) AddClaims(claims map[core.RecordRef][]consensus.ReferendumClaim) error { 141 ul.claims = claims 142 ul.cache = nil 143 return nil 144 } 145 146 func (ul *unsyncList) CalculateHash(scheme core.PlatformCryptographyScheme) ([]byte, error) { 147 if ul.cache != nil { 148 return ul.cache, nil 149 } 150 m, err := ul.GetMergedCopy() 151 if err != nil { 152 return nil, errors.Wrap(err, "[ CalculateHash ] failed to merge a node map") 153 } 154 sorted := sortedNodeList(m.ActiveList) 155 ul.cache, err = CalculateHash(scheme, sorted) 156 return ul.cache, err 157 } 158 159 func (ul *unsyncList) GetActiveNode(ref core.RecordRef) core.Node { 160 return ul.activeNodes[ref] 161 } 162 163 func (ul *unsyncList) GetActiveNodes() []core.Node { 164 return sortedNodeList(ul.activeNodes) 165 } 166 167 func (ul *unsyncList) GetMergedCopy() (*network.MergedListCopy, error) { 168 nodes := copyActiveNodes(ul.activeNodes) 169 170 var nodesJoinedDuringPrevPulse bool 171 for _, claimList := range ul.claims { 172 for _, claim := range claimList { 173 isJoin, err := mergeClaim(nodes, claim) 174 if err != nil { 175 return nil, errors.Wrap(err, "[ GetMergedCopy ] failed to merge a claim") 176 } 177 178 nodesJoinedDuringPrevPulse = nodesJoinedDuringPrevPulse || isJoin 179 } 180 } 181 182 return &network.MergedListCopy{ 183 ActiveList: nodes, 184 NodesJoinedDuringPrevPulse: nodesJoinedDuringPrevPulse, 185 }, nil 186 } 187 188 func mergeClaim(nodes map[core.RecordRef]core.Node, claim consensus.ReferendumClaim) (bool, error) { 189 isJoinClaim := false 190 switch t := claim.(type) { 191 case *consensus.NodeJoinClaim: 192 isJoinClaim = true 193 // TODO: fix version 194 node, err := ClaimToNode("", t) 195 if err != nil { 196 return isJoinClaim, errors.Wrap(err, "[ mergeClaim ] failed to convert Claim -> Node") 197 } 198 node.(MutableNode).SetState(core.NodeJoining) 199 nodes[node.ID()] = node 200 case *consensus.NodeLeaveClaim: 201 if nodes[t.NodeID] == nil { 202 break 203 } 204 205 node := nodes[t.NodeID].(MutableNode) 206 if t.ETA == 0 || !node.Leaving() { 207 node.SetLeavingETA(t.ETA) 208 } 209 } 210 211 return isJoinClaim, nil 212 } 213 214 func sortedNodeList(nodes map[core.RecordRef]core.Node) []core.Node { 215 result := make([]core.Node, len(nodes)) 216 i := 0 217 for _, node := range nodes { 218 result[i] = node 219 i++ 220 } 221 sort.Slice(result, func(i, j int) bool { 222 return result[i].ID().Compare(result[j].ID()) < 0 223 }) 224 return result 225 } 226 227 func (ul *unsyncList) IndexToRef(index int) (core.RecordRef, error) { 228 if index < 0 || index >= ul.length { 229 return core.RecordRef{}, consensus.ErrBitSetOutOfRange 230 } 231 result, ok := ul.indexToRef[index] 232 if !ok { 233 return core.RecordRef{}, consensus.ErrBitSetNodeIsMissing 234 } 235 return result, nil 236 } 237 238 func (ul *unsyncList) RefToIndex(nodeID core.RecordRef) (int, error) { 239 index, ok := ul.refToIndex[nodeID] 240 if !ok { 241 return 0, consensus.ErrBitSetIncorrectNode 242 } 243 return index, nil 244 } 245 246 func (ul *unsyncList) Length() int { 247 return ul.length 248 } 249 250 type sparseUnsyncList struct { 251 unsyncList 252 } 253 254 func newSparseUnsyncList(origin core.Node, capacity int) *sparseUnsyncList { 255 return &sparseUnsyncList{unsyncList: *newUnsyncList(origin, nil, capacity)} 256 } 257 258 func (ul *sparseUnsyncList) AddClaims(claims map[core.RecordRef][]consensus.ReferendumClaim) error { 259 err := ul.unsyncList.AddClaims(claims) 260 if err != nil { 261 return errors.Wrap(err, "[ AddClaims ] failed to add a claims") 262 } 263 264 for _, claimList := range claims { 265 for _, claim := range claimList { 266 c, ok := claim.(*consensus.NodeAnnounceClaim) 267 if !ok { 268 continue 269 } 270 271 // TODO: fix version 272 node, err := ClaimToNode("", &c.NodeJoinClaim) 273 if err != nil { 274 return errors.Wrap(err, "[ AddClaims ] failed to convert Claim -> Node") 275 } 276 // TODO: check these two 277 ul.addNode(node, int(c.NodeAnnouncerIndex)) 278 ul.addNode(ul.origin, int(c.NodeJoinerIndex)) 279 } 280 } 281 return nil 282 }