// Retrieve an object in a Merkle tree, // validating the entire path in the process. // Returns a slice of a buffer obtained from HashGet.Get(), // which might be shared and should be considered read-only. func MerkleGet(suite abstract.Suite, root []byte, path MerklePath, ctx hashid.HashGet) ([]byte, error) { // Follow pointers through intermediate levels blob := root for i := range path.Ptr { beg := path.Ptr[i] // end := beg + suite.HashLen() end := beg + 256 // change me: find hash len if end > len(blob) { return nil, errors.New("bad Merkle tree pointer offset") } id := hashid.HashId(blob[beg:end]) b, e := ctx.Get(id) // Lookup the next-level blob if e != nil { return nil, e } blob = b } // Validate and extract the actual object beg := path.Ofs end := beg + path.Len if end > len(blob) { return nil, errors.New("bad Merkle tree object offset/length") } return blob[beg:end], nil }
// Generate a Merkle proof tree for the given list of leaves, // yielding one output proof per leaf. func ProofTree(newHash func() hash.Hash, leaves []hashid.HashId) (hashid.HashId, []Proof) { if len(leaves) == 0 { return hashid.HashId(""), nil } // Determine the required tree depth nleavesArg, nleaves := len(leaves), len(leaves) depth := 0 for n := 1; n < nleaves; n <<= 1 { depth++ } // if nleaves is not a power of 2, we add 0s to fill in up to pow2 var i int for nleaves, i = (1 << uint(depth)), nleavesArg; i < nleaves; i++ { leaves = append(leaves, make([]byte, newHash().Size())) } // fmt.Println("depth=", depth, "nleaves=", nleavesArg) // Build the Merkle tree c := hashContext{newHash: newHash} tree := make([][]hashid.HashId, depth+1) tree[depth] = leaves nprev := nleaves tprev := tree[depth] for d := depth - 1; d >= 0; d-- { nnext := (nprev + 1) >> 1 // # hashes total at level i nnode := nprev >> 1 // # new nodes at level i // println("nprev", nprev, "nnext", nnext, "nnode", nnode) // fmt.Println("nprev", nprev, "nnext", nnext, "nnode", nnode) tree[d] = make([]hashid.HashId, nnext) tnext := tree[d] for i := 0; i < nnode; i++ { tnext[i] = c.hashNode(nil, tprev[i*2], tprev[i*2+1]) } // If nnode < nhash, just leave the odd one nil. nprev = nnext tprev = tnext } if nprev != 1 { panic("oops") } root := tprev[0] // Build all the individual proofs from the tree. // Some towards the end may end up being shorter than depth. proofs := make([]Proof, nleaves) for i := 0; i < nleaves; i++ { p := make([]hashid.HashId, 0, depth) // p = append(p, root) for d := depth - 1; d >= 0; d-- { h := tree[depth-d][sibling(i>>uint(d))] if h != nil { p = append(p, h) } } proofs[i] = Proof(p) } return root, proofs[:nleavesArg] }
func (s *Server) AggregateCommits(view int) []byte { //log.Println(s.Name(), "calling AggregateCommits") s.mux.Lock() // get data from s once to avoid refetching from structure Queue := s.Queue READING := s.READING PROCESSING := s.PROCESSING // messages read will now be processed READING, PROCESSING = PROCESSING, READING s.READING, s.PROCESSING = s.PROCESSING, s.READING s.Queue[READING] = s.Queue[READING][:0] // give up if nothing to process if len(Queue[PROCESSING]) == 0 { s.mux.Unlock() s.Root = make([]byte, hashid.Size) s.Proofs = make([]proof.Proof, 1) return s.Root } // pull out to be Merkle Tree leaves s.Leaves = make([]hashid.HashId, 0) for _, msg := range Queue[PROCESSING] { s.Leaves = append(s.Leaves, hashid.HashId(msg.Tsm.Sreq.Val)) } s.mux.Unlock() // non root servers keep track of rounds here if !s.IsRoot(view) { s.rLock.Lock() lsr := s.LastRound() mr := s.maxRounds s.rLock.Unlock() // if this is our last round then close the connections if lsr >= mr && mr >= 0 { s.closeChan <- true } } // create Merkle tree for this round's messages and check corectness s.Root, s.Proofs = proof.ProofTree(s.Suite().Hash, s.Leaves) if sign.DEBUG == true { if proof.CheckLocalProofs(s.Suite().Hash, s.Root, s.Leaves, s.Proofs) == true { log.Println("Local Proofs of", s.Name(), "successful for round "+strconv.Itoa(int(s.LastRound()))) } else { panic("Local Proofs" + s.Name() + " unsuccessful for round " + strconv.Itoa(int(s.LastRound()))) } } return s.Root }
func (sn *Node) SetBackLink(Round int) { prevRound := Round - 1 sn.Rounds[Round].BackLink = hashid.HashId(make([]byte, hashid.Size)) if prevRound >= FIRST_ROUND { // My Backlink = Hash(prevRound, sn.Rounds[prevRound].BackLink, sn.Rounds[prevRound].MTRoot) h := sn.suite.Hash() if sn.Rounds[prevRound] == nil { log.Errorln(sn.Name(), "not setting back link") return } h.Write(intToByteSlice(prevRound)) h.Write(sn.Rounds[prevRound].BackLink) h.Write(sn.Rounds[prevRound].MTRoot) sn.Rounds[Round].BackLink = h.Sum(nil) } }