package vassago import ( "git.openprivacy.ca/lib.surveillance.resistant.tech/trostle-parrish" "math/big" "sync" ) // Server implements the server portion of a Vassago system. type Server struct { numberOfBuckets uint bucketBuffer []byte currentBucketPointer uint lengthOfBuckets uint itemLength uint } // NewServer sets up a new server with a given number of buckets. func NewServer(numberOfBuckets uint, lengthOfBuckets uint, itemLength uint) Server { var server Server server.bucketBuffer = make([]byte, numberOfBuckets*lengthOfBuckets*itemLength) server.numberOfBuckets = numberOfBuckets server.lengthOfBuckets = lengthOfBuckets server.itemLength = itemLength server.currentBucketPointer = 0 return server } // Add item to bucket appends an item to the most recent bucket func (s *Server) AddItem(item []byte) { copy(s.bucketBuffer[s.currentBucketPointer:], item[:]) s.currentBucketPointer += s.itemLength if s.currentBucketPointer >= (s.numberOfBuckets*s.lengthOfBuckets*s.itemLength) { s.currentBucketPointer = 0 } } // PrivateLookup takes in a request from a client and calculates the response // Note this method executes an operation over every item in every bucket. func (s Server) PrivateLookup(request []trostle_parrish.Ciphertext) (result []trostle_parrish.Ciphertext) { maxBucketLength := s.lengthOfBuckets*s.itemLength var wg sync.WaitGroup result = make([]trostle_parrish.Ciphertext, maxBucketLength) reduce := make([][]trostle_parrish.Ciphertext, maxBucketLength) for i := range reduce { reduce[i] = make([]trostle_parrish.Ciphertext, s.numberOfBuckets) } calc := func(bucket int, startIndex int) { for i:=0; i< int(maxBucketLength); i++{ index := (startIndex + i) % int(s.numberOfBuckets*maxBucketLength) m := s.bucketBuffer[index] reduce[i][bucket] = big.NewInt(0).Mul(big.NewInt(int64(m)), request[bucket]) } wg.Done() } // Spin up a go routine for each bucket. for x := 0; x < int(s.numberOfBuckets); x++ { wg.Add(1) startIndexForX := int(s.currentBucketPointer) - (int(maxBucketLength)*(x+1)) if startIndexForX < 0 { startIndexForX = int(s.numberOfBuckets*s.lengthOfBuckets*s.itemLength) + startIndexForX } go calc(x, startIndexForX) } // Wait for all the go routines to finish wg.Wait() // Add each result together. for i := range reduce { total := big.NewInt(0) for j := 0; j < int(s.numberOfBuckets); j++ { total = trostle_parrish.Add(total, reduce[i][j]) } result[i] = total } return result }