github.com/braveheart12/insolar-09-08-19@v0.8.7/network/merkle/entry.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 merkle 19 20 import ( 21 "sort" 22 23 "github.com/insolar/insolar/core" 24 "github.com/pkg/errors" 25 ) 26 27 type PulseEntry struct { 28 Pulse *core.Pulse 29 } 30 31 func (pe *PulseEntry) hash(helper *merkleHelper) []byte { 32 return helper.pulseHash(pe.Pulse) 33 } 34 35 type GlobuleEntry struct { 36 *PulseEntry 37 ProofSet map[core.Node]*PulseProof 38 PulseHash []byte 39 PrevCloudHash []byte 40 GlobuleID core.GlobuleID 41 } 42 43 func (ge *GlobuleEntry) hash(helper *merkleHelper) ([]byte, error) { 44 nodeEntryByRole := nodeEntryByRole(ge.PulseEntry, ge.ProofSet) 45 var bucketHashes [][]byte 46 47 for _, role := range core.AllStaticRoles { 48 roleEntries, ok := nodeEntryByRole[role] 49 if !ok { 50 continue 51 } 52 53 sortEntries(roleEntries) 54 bucketEntryRoot, err := roleEntryRoot(roleEntries, helper) 55 56 if err != nil { 57 return nil, errors.Wrap(err, "[ hash ] Failed to create tree for bucket role entry") 58 } 59 60 bucketInfoHash := helper.bucketInfoHash(role, uint32(len(roleEntries))) 61 bucketHash := helper.bucketHash(bucketInfoHash, bucketEntryRoot) 62 bucketHashes = append(bucketHashes, bucketHash) 63 } 64 65 tree, err := treeFromHashList(bucketHashes, helper.scheme.IntegrityHasher()) 66 67 if err != nil { 68 return nil, errors.Wrap(err, "[ hash ] Failed to create tree for bucket hashes") 69 } 70 71 return tree.Root(), nil 72 } 73 74 type CloudEntry struct { 75 ProofSet []*GlobuleProof 76 PrevCloudHash []byte 77 } 78 79 func (ce *CloudEntry) hash(helper *merkleHelper) ([]byte, error) { 80 var result [][]byte 81 82 for _, proof := range ce.ProofSet { 83 globuleInfoHash := helper.globuleInfoHash(ce.PrevCloudHash, uint32(proof.GlobuleID), proof.NodeCount) 84 globuleHash := helper.globuleHash(globuleInfoHash, proof.NodeRoot) 85 result = append(result, globuleHash) 86 } 87 88 tree, err := treeFromHashList(result, helper.scheme.IntegrityHasher()) 89 if err != nil { 90 return nil, errors.Wrap(err, "[ hash ] Failed to create tree") 91 } 92 93 return tree.Root(), nil 94 } 95 96 type nodeEntry struct { 97 *PulseEntry 98 PulseProof *PulseProof 99 Node core.Node 100 } 101 102 func (ne *nodeEntry) hash(helper *merkleHelper) []byte { 103 pulseHash := ne.PulseEntry.hash(helper) 104 nodeInfoHash := helper.nodeInfoHash(pulseHash, ne.PulseProof.StateHash) 105 return helper.nodeHash(ne.PulseProof.Signature.Bytes(), nodeInfoHash) 106 } 107 108 func nodeEntryByRole(pulseEntry *PulseEntry, nodeProofs map[core.Node]*PulseProof) map[core.StaticRole][]*nodeEntry { 109 roleMap := make(map[core.StaticRole][]*nodeEntry) 110 for node, pulseProof := range nodeProofs { 111 role := node.Role() 112 roleMap[role] = append(roleMap[role], &nodeEntry{ 113 PulseEntry: pulseEntry, 114 Node: node, 115 PulseProof: pulseProof, 116 }) 117 } 118 return roleMap 119 } 120 121 func sortEntries(roleEntries []*nodeEntry) { 122 sort.SliceStable(roleEntries, func(i, j int) bool { 123 return roleEntries[i].Node.ID().Compare(roleEntries[j].Node.ID()) < 0 124 }) 125 } 126 127 func roleEntryRoot(roleEntries []*nodeEntry, helper *merkleHelper) ([]byte, error) { 128 var roleEntriesHashes [][]byte 129 for index, entry := range roleEntries { 130 bucketEntryHash := helper.bucketEntryHash(uint32(index), entry.hash(helper)) 131 roleEntriesHashes = append(roleEntriesHashes, bucketEntryHash) 132 } 133 134 tree, err := treeFromHashList(roleEntriesHashes, helper.scheme.IntegrityHasher()) 135 if err != nil { 136 return nil, errors.Wrap(err, "[ hash ] Failed to create tree") 137 } 138 139 return tree.Root(), nil 140 }