def range_compressed_MAC(self, rmin, rmax, include_rmin=True, include_rmax=True): """Get compressed MAC for a range, verifying elements past the end of range.""" if not self.root: return setmac.empty_compressed_MAC m_all = setmac.extract_compressed_MAC(self.key1, self.root.mac) if rmin: m_left = setmac.empty_compressed_MAC # invariant: after each iteration we still need to search # in t for the least value satisfying rmin constraint t = self.root while t: t.verify() if t.row_key < rmin or (t.row_key == rmin and not include_rmin): # neither t nor t.left need to be included in the # results, min satisfying is in t.right t = t.right else: # t and t.right needs to be included in the # results. min satisfying is in t.left m_left = setmac.xor_hashes(m_left, setmac.extract_compressed_MAC(self.key1, t.mac)) if t.left: m_left = setmac.xor_hashes(m_left, setmac.extract_compressed_MAC(self.key1, t.left.mac)) t = t.left else: m_left = m_all if rmax: m_right = setmac.empty_compressed_MAC # invariant: after each iteration we still need to search # in t for the greatest value satisfying rmax constraint t = self.root while t: t.verify() if t.row_key > rmax or (t.row_key == rmax and not include_rmax): # neither t nor t.right need to be included in the # results, max satisfying is in t.left t = t.left else: # t and t.left needs to be included in the # results. max satisfying is in t.right m_right = setmac.xor_hashes(m_right, setmac.extract_compressed_MAC(self.key1, t.mac)) if t.right: m_right = setmac.xor_hashes(m_right, setmac.extract_compressed_MAC(self.key1, t.right.mac)) t = t.right else: m_right = m_all return setmac.xor_hashes(m_all, setmac.xor_hashes(m_left, m_right))
def verify(self): """Verifies that the MAC stored in this node is correct, assuming that left/right have correct MACs; also verifies the BST property.""" mac = setmac.compress(self.tree.key2, {self.value: self.row_key}) if self.left: assert(self.left.key < self.key) mac = setmac.xor_hashes(mac, setmac.extract_compressed_MAC(self.tree.key1, self.left.mac)) if self.right: assert(not (self.right.key < self.key)) mac = setmac.xor_hashes(mac, setmac.extract_compressed_MAC(self.tree.key1, self.right.mac)) assert(setmac.extract_compressed_MAC(self.tree.key1, self.mac) == mac)
def update_hook(self): """Rehashes child nodes.""" mac = setmac.compress(self.tree.key2, {self.value: self.row_key}) if self.left: mac = setmac.xor_hashes(mac, setmac.extract_compressed_MAC(self.tree.key1, self.left.mac)) if self.right: mac = setmac.xor_hashes(mac, setmac.extract_compressed_MAC(self.tree.key1, self.right.mac)) self.mac = setmac.encrypt_compressed_MAC(self.tree.key1, mac) left_id = self.left_id if self.left_id else -1 right_id = self.right_id if self.right_id else -1 c = self.tree.local_conn.cursor() c.execute("UPDATE %s SET left = ?, right = ?, mac = ? WHERE row_id = ?" % self.tree.table_name, (left_id, right_id, setmac.marshall_MAC(self.mac), self.value)) self.tree.conn.commit() #self.tree.transaction.commit_unless_managed() c.close()