diff --git a/be1-go/internal/database/sqlite/chirp.go b/be1-go/internal/database/sqlite/chirp.go index 0ac1a7ae8c..429af6116f 100644 --- a/be1-go/internal/database/sqlite/chirp.go +++ b/be1-go/internal/database/sqlite/chirp.go @@ -22,32 +22,39 @@ func (s *SQLite) StoreChirpMessages(channelPath, generalChannel string, msg, gen if err != nil { return errors.NewJsonMarshalError("chirp message: %v", err) } + messageData, err := base64.URLEncoding.DecodeString(msg.Data) if err != nil { return errors.NewDecodeStringError("chirp message data: %v", err) } + generalMsgBytes, err := json.Marshal(generalMsg) if err != nil { return errors.NewInternalServerError("failed to marshal general chirp message: %v", err) } + generalMessageData, err := base64.URLEncoding.DecodeString(generalMsg.Data) if err != nil { return errors.NewInternalServerError("failed to decode general chirp message data: %v", err) } + storedTime := time.Now().UnixNano() err = s.insertMessageHelper(tx, msg.MessageID, msgBytes, messageData, storedTime) if err != nil { return err } + _, err = tx.Exec(insertChannelMessage, channelPath, msg.MessageID, true) if err != nil { return errors.NewDatabaseInsertErrorMsg("relation chirp message and chirp channel: %v", err) } + _, err = tx.Exec(insertMessage, generalMsg.MessageID, generalMsgBytes, generalMessageData, storedTime) if err != nil { return errors.NewDatabaseInsertErrorMsg("general chirp message: %v", err) } + _, err = tx.Exec(insertChannelMessage, generalChannel, generalMsg.MessageID, false) if err != nil { return errors.NewDatabaseInsertErrorMsg("relation general chirp message and general chirp channel: %v", err) diff --git a/be1-go/internal/database/sqlite/election.go b/be1-go/internal/database/sqlite/election.go index ae5b3a80cd..4557b55183 100644 --- a/be1-go/internal/database/sqlite/election.go +++ b/be1-go/internal/database/sqlite/election.go @@ -24,9 +24,11 @@ func (s *SQLite) GetLAOOrganizerPubKey(electionPath string) (kyber.Point, error) if err != nil { return nil, poperrors.NewDatabaseTransactionBeginErrorMsg(err.Error()) } + defer tx.Rollback() var organizerPubBuf []byte + err = tx.QueryRow(selectLaoOrganizerKey, electionPath). Scan(&organizerPubBuf) if err != nil { @@ -34,12 +36,14 @@ func (s *SQLite) GetLAOOrganizerPubKey(electionPath string) (kyber.Point, error) } organizerPubKey := crypto.Suite.Point() + err = organizerPubKey.UnmarshalBinary(organizerPubBuf) if err != nil { return nil, poperrors.NewInternalServerError("failed to unmarshal lao organizer public key: %v", err) } err = tx.Commit() + if err != nil { return nil, poperrors.NewDatabaseTransactionCommitErrorMsg(err.Error()) } @@ -52,23 +56,26 @@ func (s *SQLite) GetElectionSecretKey(electionPath string) (kyber.Scalar, error) defer dbLock.Unlock() var electionSecretBuf []byte - err := s.database.QueryRow(selectSecretKey, electionPath). - Scan(&electionSecretBuf) + + err := s.database.QueryRow(selectSecretKey, electionPath).Scan(&electionSecretBuf) if err != nil { return nil, poperrors.NewDatabaseSelectErrorMsg("election secret key: %v", err) } electionSecretKey := crypto.Suite.Scalar() err = electionSecretKey.UnmarshalBinary(electionSecretBuf) + if err != nil { return nil, poperrors.NewInternalServerError("failed to unmarshal election secret key: %v", err) } + return electionSecretKey, nil } func (s *SQLite) getElectionState(electionPath string) (string, error) { var state string + err := s.database.QueryRow(selectLastElectionMessage, electionPath, channel.ElectionObject, @@ -78,6 +85,7 @@ func (s *SQLite) getElectionState(electionPath string) (string, error) { if err != nil && !errors.Is(err, sql.ErrNoRows) { return "", poperrors.NewDatabaseSelectErrorMsg("election state: %v", err) } + return state, nil } @@ -101,6 +109,7 @@ func (s *SQLite) IsElectionStarted(electionPath string) (bool, error) { if err != nil { return false, err } + return state == channel.ElectionActionOpen, nil } @@ -112,6 +121,7 @@ func (s *SQLite) IsElectionEnded(electionPath string) (bool, error) { if err != nil { return false, err } + return state == channel.ElectionActionEnd, nil } @@ -120,11 +130,13 @@ func (s *SQLite) GetElectionCreationTime(electionPath string) (int64, error) { defer dbLock.Unlock() var creationTime int64 + err := s.database.QueryRow(selectElectionCreationTime, electionPath, channel.ElectionObject, channel.ElectionActionSetup). Scan(&creationTime) if err != nil { return 0, poperrors.NewDatabaseSelectErrorMsg("election creation time: %v", err) } + return creationTime, nil } @@ -133,15 +145,16 @@ func (s *SQLite) GetElectionType(electionPath string) (string, error) { defer dbLock.Unlock() var electionType string + err := s.database.QueryRow(selectElectionType, electionPath, channel.ElectionObject, channel.ElectionActionSetup). Scan(&electionType) - if err != nil { return "", poperrors.NewDatabaseSelectErrorMsg("election type: %v", err) } + return electionType, nil } @@ -163,32 +176,39 @@ func (s *SQLite) GetElectionAttendees(electionPath string) (map[string]struct{}, } var rollCallClose mlao.RollCallClose + err = json.Unmarshal(rollCallCloseBytes, &rollCallClose) if err != nil { return nil, poperrors.NewJsonUnmarshalError("roll call close message data: %v", err) } attendeesMap := make(map[string]struct{}) + for _, attendee := range rollCallClose.Attendees { attendeesMap[attendee] = struct{}{} } + return attendeesMap, nil } func (s *SQLite) getElectionSetup(electionPath string, tx *sql.Tx) (mlao.ElectionSetup, error) { var electionSetupBytes []byte + err := tx.QueryRow(selectElectionSetup, electionPath, channel.ElectionObject, channel.ElectionActionSetup). Scan(&electionSetupBytes) + if err != nil { return mlao.ElectionSetup{}, poperrors.NewDatabaseSelectErrorMsg("election setup message data: %v", err) } var electionSetup mlao.ElectionSetup + err = json.Unmarshal(electionSetupBytes, &electionSetup) if err != nil { return mlao.ElectionSetup{}, poperrors.NewJsonUnmarshalError("election setup message data: %v", err) } + return electionSetup, nil } @@ -201,6 +221,7 @@ func (s *SQLite) GetElectionQuestions(electionPath string) (map[string]telection return nil, poperrors.NewDatabaseTransactionBeginErrorMsg(err.Error()) } + defer tx.Rollback() electionSetup, err := s.getElectionSetup(electionPath, tx) @@ -208,6 +229,7 @@ func (s *SQLite) GetElectionQuestions(electionPath string) (map[string]telection return nil, err } + questions, err := getQuestionsFromMessage(electionSetup) if err != nil { return nil, err @@ -218,6 +240,7 @@ func (s *SQLite) GetElectionQuestions(electionPath string) (map[string]telection return nil, poperrors.NewDatabaseTransactionCommitErrorMsg(err.Error()) } + return questions, nil } @@ -229,6 +252,7 @@ func (s *SQLite) GetElectionQuestionsWithValidVotes(electionPath string) (map[st if err != nil { return nil, poperrors.NewDatabaseTransactionBeginErrorMsg(err.Error()) } + defer tx.Rollback() electionSetup, err := s.getElectionSetup(electionPath, tx) @@ -244,6 +268,7 @@ func (s *SQLite) GetElectionQuestionsWithValidVotes(electionPath string) (map[st if err != nil { return nil, poperrors.NewDatabaseSelectErrorMsg("cast vote messages: %v", err) } + defer rows.Close() for rows.Next() { @@ -253,36 +278,46 @@ func (s *SQLite) GetElectionQuestionsWithValidVotes(electionPath string) (map[st if err = rows.Scan(&voteBytes, &msgID, &sender); err != nil { return nil, poperrors.NewDatabaseScanErrorMsg("cast vote message: %v", err) } + var vote melection.VoteCastVote err = json.Unmarshal(voteBytes, &vote) + if err != nil { return nil, poperrors.NewJsonUnmarshalError("cast vote message data: %v", err) } + err = updateVote(msgID, sender, vote, questions) if err != nil { return nil, err } } + if err = rows.Err(); err != nil { return nil, poperrors.NewDatabaseIteratorErrorMsg("cast vote messages: %v", err) } + err = tx.Commit() + if err != nil { return nil, poperrors.NewDatabaseTransactionCommitErrorMsg(err.Error()) } + return questions, nil } func getQuestionsFromMessage(electionSetup mlao.ElectionSetup) (map[string]telection.Question, error) { questions := make(map[string]telection.Question) + for _, question := range electionSetup.Questions { ballotOptions := make([]string, len(question.BallotOptions)) copy(ballotOptions, question.BallotOptions) _, ok := questions[question.ID] + if ok { return nil, poperrors.NewInvalidMessageFieldError("duplicate question ID in election setup message data: %s", question.ID) } + questions[question.ID] = telection.Question{ ID: []byte(question.ID), BallotOptions: ballotOptions, @@ -290,16 +325,20 @@ func getQuestionsFromMessage(electionSetup mlao.ElectionSetup) (map[string]telec Method: question.VotingMethod, } } + return questions, nil } func updateVote(msgID, sender string, castVote melection.VoteCastVote, questions map[string]telection.Question) error { for idx, vote := range castVote.Votes { question, ok := questions[vote.Question] + if !ok { return poperrors.NewInvalidMessageFieldError("question not found in election setup for vote number %d sent by %s", idx, sender) } + earlierVote, ok := question.ValidVotes[sender] + if !ok || earlierVote.VoteTime < castVote.CreatedAt { question.ValidVotes[sender] = telection.ValidVote{ MsgID: msgID, @@ -309,6 +348,7 @@ func updateVote(msgID, sender string, castVote melection.VoteCastVote, questions } } } + return nil } @@ -326,37 +366,44 @@ func (s *SQLite) StoreElectionEndWithResult(channelPath string, msg, electionRes if err != nil { return poperrors.NewJsonMarshalError("election end message: %v", err) } + messageData, err := base64.URLEncoding.DecodeString(msg.Data) if err != nil { return poperrors.NewDecodeStringError("election end message data: %v", err) } + electionResult, err := base64.URLEncoding.DecodeString(electionResultMsg.Data) if err != nil { return poperrors.NewInternalServerError("failed to decode election result message data: %v", err) } + electionResultMsgBytes, err := json.Marshal(electionResultMsg) if err != nil { return poperrors.NewJsonMarshalError("failed to marshal election result message: %v", err) } + storedTime := time.Now().UnixNano() err = s.insertMessageHelper(tx, msg.MessageID, msgBytes, messageData, storedTime) if err != nil { return err - } + _, err = tx.Exec(insertChannelMessage, channelPath, msg.MessageID, true) if err != nil { return poperrors.NewDatabaseInsertErrorMsg("relation election end message and election channel: %v", err) } + _, err = tx.Exec(insertMessage, electionResultMsg.MessageID, electionResultMsgBytes, electionResult, storedTime) if err != nil { return poperrors.NewDatabaseInsertErrorMsg("election result message: %v", err) } + _, err = tx.Exec(insertChannelMessage, channelPath, electionResultMsg.MessageID, false) if err != nil { return poperrors.NewDatabaseInsertErrorMsg("relation election result message and election channel: %v", err) } + err = tx.Commit() if err != nil { diff --git a/be1-go/internal/database/sqlite/lao.go b/be1-go/internal/database/sqlite/lao.go index f8b1665f7a..9b435d27e8 100644 --- a/be1-go/internal/database/sqlite/lao.go +++ b/be1-go/internal/database/sqlite/lao.go @@ -18,10 +18,12 @@ func (s *SQLite) GetRollCallState(channelPath string) (string, error) { defer dbLock.Unlock() var state string + err := s.database.QueryRow(selectLastRollCallMessage, channel.RollCallObject, channelPath).Scan(&state) if err != nil { return "", poperrors.NewDatabaseSelectErrorMsg(err.Error()) } + return state, nil } @@ -44,17 +46,21 @@ func (s *SQLite) CheckPrevOpenOrReopenID(channelPath, nextID string) (bool, erro switch lastAction { case channel.RollCallActionOpen: var rollCallOpen mlao.RollCallOpen + err = json.Unmarshal(lastMsg, &rollCallOpen) if err != nil { return false, poperrors.NewInternalServerError("failed to unmarshal last roll call open message: %v", err) } + return rollCallOpen.UpdateID == nextID, nil case channel.RollCallActionReOpen: var rollCallReOpen mlao.RollCallReOpen + err = json.Unmarshal(lastMsg, &rollCallReOpen) if err != nil { return false, poperrors.NewInternalServerError("failed to unmarshal last roll call re open message: %v", err) } + return rollCallReOpen.UpdateID == nextID, nil } @@ -80,17 +86,21 @@ func (s *SQLite) CheckPrevCreateOrCloseID(channelPath, nextID string) (bool, err switch lastAction { case channel.RollCallActionCreate: var rollCallCreate mlao.RollCallCreate + err = json.Unmarshal(lastMsg, &rollCallCreate) if err != nil { return false, poperrors.NewInternalServerError("failed to unmarshal last roll call create message: %v", err) } + return rollCallCreate.ID == nextID, nil case channel.RollCallActionClose: var rollCallClose mlao.RollCallClose + err = json.Unmarshal(lastMsg, &rollCallClose) if err != nil { return false, poperrors.NewInternalServerError("failed to unmarshal last roll call close message: %v", err) } + return rollCallClose.UpdateID == nextID, nil } @@ -102,12 +112,14 @@ func (s *SQLite) GetLaoWitnesses(laoPath string) (map[string]struct{}, error) { defer dbLock.Unlock() var witnesses []string + err := s.database.QueryRow(selectLaoWitnesses, laoPath, channel.LAOObject, channel.LAOActionCreate).Scan(&witnesses) if err != nil { return nil, poperrors.NewDatabaseSelectErrorMsg("lao witnesses: %v", err) } var witnessesMap = make(map[string]struct{}) + for _, witness := range witnesses { witnessesMap[witness] = struct{}{} } @@ -123,6 +135,7 @@ func (s *SQLite) StoreRollCallClose(channels []string, laoPath string, msg mmess if err != nil { return poperrors.NewDatabaseTransactionBeginErrorMsg(err.Error()) } + defer tx.Rollback() messageData, err := base64.URLEncoding.DecodeString(msg.Data) @@ -139,6 +152,7 @@ func (s *SQLite) StoreRollCallClose(channels []string, laoPath string, msg mmess if err != nil { return err } + _, err = tx.Exec(insertChannelMessage, laoPath, msg.MessageID, true) if err != nil { return poperrors.NewDatabaseInsertErrorMsg("relation roll call close message and lao channel: %v", err) @@ -158,12 +172,13 @@ func (s *SQLite) StoreRollCallClose(channels []string, laoPath string, msg mmess return poperrors.NewDatabaseInsertErrorMsg("channel %s: %v", channelPath, err) } } + err = tx.Commit() if err != nil { return poperrors.NewDatabaseTransactionCommitErrorMsg(err.Error()) } - return nil + return nil } func (s *SQLite) storeElectionHelper( @@ -178,6 +193,7 @@ func (s *SQLite) storeElectionHelper( if err != nil { return poperrors.NewJsonMarshalError("election create message: %v", err) } + messageData, err := base64.URLEncoding.DecodeString(msg.Data) if err != nil { return poperrors.NewDecodeStringError("election create message data: %v", err) @@ -187,6 +203,7 @@ func (s *SQLite) storeElectionHelper( if err != nil { return poperrors.NewKeyMarshalError("election public key: %v", err) } + electionSecretBuf, err := electionSecretKey.MarshalBinary() if err != nil { return poperrors.NewKeyMarshalError("election secret key: %v", err) @@ -196,18 +213,22 @@ func (s *SQLite) storeElectionHelper( if err != nil { return err } + _, err = tx.Exec(insertChannelMessage, laoPath, msg.MessageID, true) if err != nil { return poperrors.NewDatabaseInsertErrorMsg("relation election create message and lao channel: %v", err) } + _, err = tx.Exec(insertChannel, electionPath, channelTypeToID[channel.ElectionObject], laoPath) if err != nil { return poperrors.NewDatabaseInsertErrorMsg("election channel: %v", err) } + _, err = tx.Exec(insertChannelMessage, electionPath, msg.MessageID, false) if err != nil { return poperrors.NewDatabaseInsertErrorMsg("relation election create message and election channel: %v", err) } + _, err = tx.Exec(insertKeys, electionPath, electionPubBuf, electionSecretBuf) if err != nil { return poperrors.NewDatabaseInsertErrorMsg("election keys: %v", err) @@ -229,6 +250,7 @@ func (s *SQLite) StoreElection( if err != nil { return poperrors.NewDatabaseTransactionBeginErrorMsg(err.Error()) } + defer tx.Rollback() storedTime := time.Now().UnixNano() @@ -242,6 +264,7 @@ func (s *SQLite) StoreElection( if err != nil { return poperrors.NewDatabaseTransactionCommitErrorMsg(err.Error()) } + return nil } @@ -258,6 +281,7 @@ func (s *SQLite) StoreElectionWithElectionKey( if err != nil { return poperrors.NewDatabaseTransactionBeginErrorMsg(err.Error()) } + defer tx.Rollback() storedTime := time.Now().UnixNano() @@ -271,6 +295,7 @@ func (s *SQLite) StoreElectionWithElectionKey( if err != nil { return poperrors.NewDecodeStringError("failed to decode election key message data: %v", err) } + electionKeyMsgBytes, err := json.Marshal(electionKeyMsg) if err != nil { return poperrors.NewInternalServerError("failed to marshal election key message: %v", err) @@ -280,6 +305,7 @@ func (s *SQLite) StoreElectionWithElectionKey( if err != nil { return poperrors.NewDatabaseInsertErrorMsg("election key message: %v", err) } + _, err = tx.Exec(insertChannelMessage, electionPath, electionKeyMsg.MessageID, false) if err != nil { return poperrors.NewDatabaseInsertErrorMsg("relation election key message and election channel: %v", err) @@ -289,5 +315,6 @@ func (s *SQLite) StoreElectionWithElectionKey( if err != nil { return poperrors.NewDatabaseTransactionCommitErrorMsg(err.Error()) } + return nil } diff --git a/be1-go/internal/database/sqlite/query.go b/be1-go/internal/database/sqlite/query.go index 2ed034c892..2e2d0364f2 100644 --- a/be1-go/internal/database/sqlite/query.go +++ b/be1-go/internal/database/sqlite/query.go @@ -18,6 +18,7 @@ func (s *SQLite) GetAllMessagesFromChannel(channelPath string) ([]mmessage.Messa if err != nil { return nil, poperrors.NewDatabaseSelectErrorMsg("messages from channel %s: %v", channelPath, err) } + defer rows.Close() messages := make([]mmessage.Message, 0) @@ -26,10 +27,12 @@ func (s *SQLite) GetAllMessagesFromChannel(channelPath string) ([]mmessage.Messa if err = rows.Scan(&messageByte); err != nil { return nil, poperrors.NewDatabaseScanErrorMsg(err.Error()) } + var msg mmessage.Message if err = json.Unmarshal(messageByte, &msg); err != nil { return nil, poperrors.NewInternalServerError("failed to unmarshal message: %v", err) } + messages = append(messages, msg) } @@ -45,8 +48,10 @@ func (s *SQLite) GetResultForGetMessagesByID(params map[string][]string) (map[st defer dbLock.Unlock() var interfaces []interface{} + // isBaseChannel must be true interfaces = append(interfaces, true) + for _, value := range params { for _, v := range value { interfaces = append(interfaces, v) @@ -61,22 +66,28 @@ func (s *SQLite) GetResultForGetMessagesByID(params map[string][]string) (map[st "FROM message JOIN channelMessage on message.messageID = channelMessage.messageID "+ "WHERE isBaseChannel = ? "+ "AND message.messageID IN ("+strings.Repeat("?,", len(interfaces)-2)+"?"+") ", interfaces...) + if err != nil { return nil, poperrors.NewDatabaseSelectErrorMsg("get messages by id: %v", err) } + defer rows.Close() result := make(map[string][]mmessage.Message) + for rows.Next() { var messageByte []byte var channelPath string + if err = rows.Scan(&messageByte, &channelPath); err != nil { return nil, poperrors.NewDatabaseScanErrorMsg(err.Error()) } + var msg mmessage.Message if err = json.Unmarshal(messageByte, &msg); err != nil { return nil, poperrors.NewInternalServerError("failed to unmarshal message: %v", err) } + result[channelPath] = append(result[channelPath], msg) } @@ -94,6 +105,7 @@ func (s *SQLite) GetParamsForGetMessageByID(params map[string][]string) (map[str var interfaces []interface{} interfaces = append(interfaces, true) + for _, value := range params { for _, v := range value { interfaces = append(interfaces, v) @@ -108,18 +120,22 @@ func (s *SQLite) GetParamsForGetMessageByID(params map[string][]string) (map[str "FROM message JOIN channelMessage on message.messageID = channelMessage.messageID "+ "WHERE isBaseChannel = ? "+ "AND message.messageID IN ("+strings.Repeat("?,", len(interfaces)-2)+"?"+") ", interfaces...) + if err != nil { return nil, poperrors.NewDatabaseSelectErrorMsg("get messages by id: %v", err) } + defer rows.Close() result := make(map[string]struct{}) for rows.Next() { var messageID string var channelPath string + if err = rows.Scan(&messageID, &channelPath); err != nil { return nil, poperrors.NewDatabaseScanErrorMsg(err.Error()) } + result[messageID] = struct{}{} } @@ -135,6 +151,7 @@ func (s *SQLite) GetParamsForGetMessageByID(params map[string][]string) (map[str } } } + return missingIDs, nil } @@ -146,18 +163,21 @@ func (s *SQLite) CheckRumor(senderID string, rumorID int, timestamp mrumor.Rumor if err != nil { return false, false, poperrors.NewDatabaseTransactionBeginErrorMsg(err.Error()) } + defer tx.Rollback() myTimestamp, err := s.GetRumorTimestampHelper(tx) if err != nil { return false, false, err } + err = tx.Commit() if err != nil { return false, false, poperrors.NewDatabaseTransactionCommitErrorMsg(err.Error()) } isValid, alreadyExist := s.CheckTimestampHelper(senderID, rumorID, timestamp, myTimestamp) + return isValid, alreadyExist, nil } @@ -168,6 +188,7 @@ func (s *SQLite) CheckTimestampHelper(senderID string, rumorID int, alreadyExist := false curRumorID, ok := myTimestamp[senderID] + if ok && rumorID <= curRumorID { alreadyExist = true } else if (!ok && rumorID != 0) || (ok && rumorID > curRumorID+1) { @@ -176,6 +197,7 @@ func (s *SQLite) CheckTimestampHelper(senderID string, rumorID int, isValid = true for senderID1, rumorID1 := range timestamp { rumorID2, ok := myTimestamp[senderID1] + if (!ok || rumorID1 > rumorID2) && senderID1 != senderID { isValid = false break @@ -224,6 +246,7 @@ func (s *SQLite) StoreRumor(rumorID int, sender string, timestamp mrumor.RumorTi if err != nil { return poperrors.NewDatabaseTransactionCommitErrorMsg(err.Error()) } + return nil } @@ -234,10 +257,12 @@ func StoreUnprocessedHelper(tx *sql.Tx, rumorID int, sender string, unprocessed if err != nil { return poperrors.NewJsonMarshalError("unprocessed message: %v", err) } + _, err = tx.Exec(insertUnprocessedMessage, msg.MessageID, channelPath, msgByte) if err != nil { return poperrors.NewDatabaseInsertErrorMsg("unprocessed message: %v", err) } + _, err = tx.Exec(insertUnprocessedMessageRumor, msg.MessageID, rumorID, sender) if err != nil { return poperrors.NewDatabaseInsertErrorMsg("relation unprocessed message and rumor: %v", err) @@ -255,6 +280,7 @@ func (s *SQLite) GetUnprocessedMessagesByChannel() (map[string][]mmessage.Messag if err != nil { return nil, poperrors.NewDatabaseSelectErrorMsg("all unprocessed messages: %v", err) } + defer rows.Close() result := make(map[string][]mmessage.Message) @@ -262,15 +288,19 @@ func (s *SQLite) GetUnprocessedMessagesByChannel() (map[string][]mmessage.Messag for rows.Next() { var channelPath string var messageByte []byte + if err = rows.Scan(&channelPath, &messageByte); err != nil { return nil, poperrors.NewDatabaseScanErrorMsg("unprocessed message and channelPath: %v", err) } + var msg mmessage.Message if err = json.Unmarshal(messageByte, &msg); err != nil { return nil, poperrors.NewInternalServerError("failed to unmarshal unprocessed message: %v", err) } + result[channelPath] = append(result[channelPath], msg) } + return result, nil } @@ -282,13 +312,16 @@ func (s *SQLite) AddMessageToMyRumor(messageID string) (int, error) { if err != nil { return -1, poperrors.NewDatabaseTransactionBeginErrorMsg(err.Error()) } + defer tx.Rollback() _, err = tx.Exec(insertMessageToMyRumor, messageID, serverKeysPath) if err != nil { return -1, poperrors.NewDatabaseInsertErrorMsg("message to the current rumor: %v", err) } + var count int + err = tx.QueryRow(selectCountMyRumor, serverKeysPath).Scan(&count) if err != nil { return -1, poperrors.NewDatabaseSelectErrorMsg("number of messages in the current rumor: %v", err) @@ -298,6 +331,7 @@ func (s *SQLite) AddMessageToMyRumor(messageID string) (int, error) { if err != nil { return -1, poperrors.NewDatabaseTransactionCommitErrorMsg(err.Error()) } + return count, nil } @@ -309,18 +343,22 @@ func (s *SQLite) GetAndIncrementMyRumor() (bool, mrumor.ParamsRumor, error) { if err != nil { return false, mrumor.ParamsRumor{}, poperrors.NewDatabaseTransactionBeginErrorMsg(err.Error()) } + defer tx.Rollback() rows, err := tx.Query(selectMyRumorMessages, true, serverKeysPath, serverKeysPath) if err != nil { return false, mrumor.ParamsRumor{}, poperrors.NewDatabaseSelectErrorMsg("current rumor params: %v", err) } + defer rows.Close() messages := make(map[string][]mmessage.Message) + for rows.Next() { var msgBytes []byte var channelPath string + if err = rows.Scan(&msgBytes, &channelPath); err != nil { return false, mrumor.ParamsRumor{}, poperrors.NewDatabaseScanErrorMsg(err.Error()) } @@ -339,6 +377,7 @@ func (s *SQLite) GetAndIncrementMyRumor() (bool, mrumor.ParamsRumor, error) { var rumorID int var sender string + err = tx.QueryRow(selectMyRumorInfos, serverKeysPath).Scan(&rumorID, &sender) if err != nil { return false, mrumor.ParamsRumor{}, poperrors.NewDatabaseSelectCurrRumorInfosErrorMsg(err.Error()) @@ -374,7 +413,9 @@ func (s *SQLite) GetAndIncrementMyRumor() (bool, mrumor.ParamsRumor, error) { return true, params, nil } -func newRumorParams(rumorID int, sender string, messages map[string][]mmessage.Message, timestamp mrumor.RumorTimestamp) mrumor.ParamsRumor { +func newRumorParams(rumorID int, sender string, + messages map[string][]mmessage.Message, timestamp mrumor.RumorTimestamp) mrumor.ParamsRumor { + return mrumor.ParamsRumor{ RumorID: rumorID, SenderID: sender, @@ -389,6 +430,7 @@ func (s *SQLite) GetRumorTimestampHelper(tx *sql.Tx) (mrumor.RumorTimestamp, err if err != nil { return nil, poperrors.NewDatabaseSelectErrorMsg("rumor state: %v", err) } + defer rows.Close() timestamp := make(mrumor.RumorTimestamp) @@ -396,9 +438,11 @@ func (s *SQLite) GetRumorTimestampHelper(tx *sql.Tx) (mrumor.RumorTimestamp, err for rows.Next() { var sender string var rumorID int + if err = rows.Scan(&rumorID, &sender); err != nil { return nil, poperrors.NewDatabaseScanErrorMsg(err.Error()) } + timestamp[sender] = rumorID } @@ -408,6 +452,7 @@ func (s *SQLite) GetRumorTimestampHelper(tx *sql.Tx) (mrumor.RumorTimestamp, err var rumorID int var sender string + err = tx.QueryRow(selectMyRumorInfos, serverKeysPath).Scan(&rumorID, &sender) if err != nil { return nil, poperrors.NewDatabaseSelectCurrRumorInfosErrorMsg(err.Error()) @@ -430,6 +475,7 @@ func (s *SQLite) GetRumorTimestamp() (mrumor.RumorTimestamp, error) { if err != nil { return nil, poperrors.NewDatabaseTransactionBeginErrorMsg(err.Error()) } + defer tx.Rollback() timestamp, err := s.GetRumorTimestampHelper(tx) @@ -453,10 +499,12 @@ func (s *SQLite) GetAllRumorParams() ([]mrumor.ParamsRumor, error) { if err != nil { return nil, poperrors.NewDatabaseTransactionBeginErrorMsg(err.Error()) } + defer tx.Rollback() var myRumorID int var mySender string + err = tx.QueryRow(selectMyRumorInfos, serverKeysPath).Scan(&myRumorID, &mySender) if err != nil { return nil, poperrors.NewDatabaseSelectCurrRumorInfosErrorMsg(err.Error()) @@ -477,6 +525,7 @@ func (s *SQLite) GetAllRumorParams() ([]mrumor.ParamsRumor, error) { } else if param.SenderID == "" { continue } + params = append(params, param) } @@ -489,6 +538,7 @@ func (s *SQLite) GetAllRumorParams() ([]mrumor.ParamsRumor, error) { func (s *SQLite) GetRumorParamsHelper(tx *sql.Tx, rows *sql.Rows, mySender string, myRumorID int) (mrumor.ParamsRumor, error) { + var rumorID int var sender string var timestampByte []byte @@ -502,6 +552,7 @@ func (s *SQLite) GetRumorParamsHelper(tx *sql.Tx, rows *sql.Rows, } var timestamp mrumor.RumorTimestamp + if err := json.Unmarshal(timestampByte, ×tamp); err != nil { return mrumor.ParamsRumor{}, poperrors.NewInternalServerError("failed to unmarshal timestamp: %v", err) } @@ -532,18 +583,23 @@ func (s *SQLite) GetMessagesFromRumorHelper(tx *sql.Tx, rumorID int, args []inte if err != nil { return poperrors.NewDatabaseSelectErrorMsg("messages from rumor %d: %v", rumorID, err) } + defer rows.Close() for rows.Next() { var channelPath string var messageByte []byte + if err = rows.Scan(&channelPath, &messageByte); err != nil { return poperrors.NewDatabaseScanErrorMsg(err.Error()) } + var msg mmessage.Message + if err = json.Unmarshal(messageByte, &msg); err != nil { return poperrors.NewInternalServerError("failed to unmarshal message from rumor %d: %v", rumorID, err) } + messages[channelPath] = append(messages[channelPath], msg) } diff --git a/be1-go/internal/database/sqlite/reaction.go b/be1-go/internal/database/sqlite/reaction.go index ec0e051a69..438605806e 100644 --- a/be1-go/internal/database/sqlite/reaction.go +++ b/be1-go/internal/database/sqlite/reaction.go @@ -14,6 +14,7 @@ func (s *SQLite) IsAttendee(laoPath, poptoken string) (bool, error) { defer dbLock.Unlock() var rollCallCloseBytes []byte + err := s.database.QueryRow(selectLastRollCallClose, laoPath, channel.RollCallObject, @@ -25,6 +26,7 @@ func (s *SQLite) IsAttendee(laoPath, poptoken string) (bool, error) { } var rollCallClose mlao.RollCallClose + err = json.Unmarshal(rollCallCloseBytes, &rollCallClose) if err != nil { return false, poperrors.NewInternalServerError("failed to unmarshal last roll call close message: %v", err) @@ -46,6 +48,7 @@ func (s *SQLite) GetReactionSender(messageID string) (string, error) { var sender string var object string var action string + err := s.database.QueryRow(selectSender, messageID).Scan(&sender, &object, &action) if err != nil && errors.Is(err, sql.ErrNoRows) { return "", nil diff --git a/be1-go/internal/database/sqlite/root.go b/be1-go/internal/database/sqlite/root.go index 15dd37a966..06c4af44cf 100644 --- a/be1-go/internal/database/sqlite/root.go +++ b/be1-go/internal/database/sqlite/root.go @@ -29,6 +29,7 @@ func (s *SQLite) StoreLaoWithLaoGreet( if err != nil { return poperrors.NewJsonMarshalError("lao create message: %v", err) } + laoGreetMsgByte, err := json.Marshal(laoGreetMsg) if err != nil { return poperrors.NewInternalServerError("lao greet message: %v", err) @@ -38,6 +39,7 @@ func (s *SQLite) StoreLaoWithLaoGreet( if err != nil { return poperrors.NewDecodeStringError("lao create message data in database: %v", err) } + laoGreetData, err := base64.URLEncoding.DecodeString(laoGreetMsg.Data) if err != nil { return poperrors.NewInternalServerError("failed to decode string: lao greet message data in database: %v", err) @@ -56,6 +58,7 @@ func (s *SQLite) StoreLaoWithLaoGreet( if err != nil { return err } + _, err = tx.Exec(insertChannelMessage, channel.Root, msg.MessageID, true) if err != nil { return poperrors.NewDatabaseInsertErrorMsg("relation lao create message and root channel: %v", err) @@ -70,10 +73,12 @@ func (s *SQLite) StoreLaoWithLaoGreet( if err != nil { return poperrors.NewDatabaseInsertErrorMsg("lao organizer public key: %v", err) } + _, err = tx.Exec(insertMessage, laoGreetMsg.MessageID, laoGreetMsgByte, laoGreetData, storedTime) if err != nil { return poperrors.NewDatabaseInsertErrorMsg("lao greet message: %v", err) } + _, err = tx.Exec(insertChannelMessage, laoPath, laoGreetMsg.MessageID, false) if err != nil { return poperrors.NewDatabaseInsertErrorMsg("relation lao greet message lao channel: %v", err) diff --git a/be1-go/internal/database/sqlite/sqlite.go b/be1-go/internal/database/sqlite/sqlite.go index 92916449f3..c2c991ad84 100644 --- a/be1-go/internal/database/sqlite/sqlite.go +++ b/be1-go/internal/database/sqlite/sqlite.go @@ -20,6 +20,7 @@ func (s *SQLite) GetServerKeys() (kyber.Point, kyber.Scalar, error) { var serverPubBuf64 string var serverSecBuf64 string + err := s.database.QueryRow(selectKeys, serverKeysPath).Scan(&serverPubBuf64, &serverSecBuf64) if err != nil { return nil, nil, poperrors.NewDatabaseSelectErrorMsg("server keys: %v", err) @@ -40,7 +41,9 @@ func (s *SQLite) GetServerKeys() (kyber.Point, kyber.Scalar, error) { if err != nil { return nil, nil, poperrors.NewKeyMarshalError("server public key: %v", err) } + serverSecKey := crypto.Suite.Scalar() + err = serverSecKey.UnmarshalBinary(serverSecBuf) if err != nil { return nil, nil, poperrors.NewKeyMarshalError("server secret key: %v", err) @@ -54,32 +57,40 @@ func (s *SQLite) GetOrganizerPubKey(laoPath string) (kyber.Point, error) { defer dbLock.Unlock() var organizerPubBuf []byte + err := s.database.QueryRow(selectPublicKey, laoPath).Scan(&organizerPubBuf) if err != nil { return nil, poperrors.NewDatabaseSelectErrorMsg("organizer public key: %v", err) } + organizerPubKey := crypto.Suite.Point() + err = organizerPubKey.UnmarshalBinary(organizerPubBuf) if err != nil { return nil, poperrors.NewKeyMarshalError("organizer public key: %v", err) } + return organizerPubKey, nil } func (s *SQLite) insertMessageHelper(tx *sql.Tx, messageID string, msg, messageData []byte, storedTime int64) error { _, err := tx.Exec(insertMessage, messageID, msg, messageData, storedTime) + if err != nil { return poperrors.NewDatabaseInsertErrorMsg(err.Error()) } + _, err = tx.Exec(tranferUnprocessedMessageRumor, messageID) if err != nil { return poperrors.NewDatabaseInsertErrorMsg("relation message rumor from relation unprocessed message rumor: %v", err) } + _, err = tx.Exec(deleteUnprocessedMessageRumor, messageID) if err != nil { return poperrors.NewDatabaseDeleteErrorMsg("relation unprocessed message rumor: %v", err) } + _, err = tx.Exec(deleteUnprocessedMessage, messageID) if err != nil { return poperrors.NewDatabaseDeleteErrorMsg("unprocessed message: %v", err) @@ -96,6 +107,7 @@ func (s *SQLite) StoreMessageAndData(channelPath string, msg mmessage.Message) e if err != nil { return err } + defer tx.Rollback() messageData, err := base64.URLEncoding.DecodeString(msg.Data) @@ -104,9 +116,11 @@ func (s *SQLite) StoreMessageAndData(channelPath string, msg mmessage.Message) e } msgByte, err := json.Marshal(msg) + if err != nil { return poperrors.NewJsonMarshalError(err.Error()) } + err = s.insertMessageHelper(tx, msg.MessageID, msgByte, messageData, time.Now().UnixNano()) if err != nil { return err @@ -131,6 +145,7 @@ func (s *SQLite) HasMessage(messageID string) (bool, error) { defer dbLock.Unlock() var msgID string + err := s.database.QueryRow(selectMessageID, messageID).Scan(&msgID) if err != nil && errors.Is(err, sql.ErrNoRows) { return false, nil @@ -154,37 +169,46 @@ func (s *SQLite) GetMessagesByIDUtil(IDs []string) (map[string]mmessage.Message, } IDsInterface := make([]interface{}, len(IDs)) + for i, v := range IDs { IDsInterface[i] = v } + rows, err := s.database.Query("SELECT messageID, message "+ "FROM message "+ "WHERE messageID IN ("+strings.Repeat("?,", len(IDs)-1)+"?"+")", IDsInterface...) + if err != nil && !errors.Is(err, sql.ErrNoRows) { return nil, poperrors.NewDatabaseSelectErrorMsg("messages: %v", err) } else if errors.Is(err, sql.ErrNoRows) { return make(map[string]mmessage.Message), nil } + defer rows.Close() messagesByID := make(map[string]mmessage.Message, len(IDs)) + for rows.Next() { var messageID string var messageByte []byte + if err = rows.Scan(&messageID, &messageByte); err != nil { return nil, poperrors.NewDatabaseScanErrorMsg(err.Error()) } var msg mmessage.Message + if err = json.Unmarshal(messageByte, &msg); err != nil { return nil, poperrors.NewJsonUnmarshalError(err.Error()) } + messagesByID[messageID] = msg } if err = rows.Err(); err != nil { return nil, poperrors.NewDatabaseIteratorErrorMsg("messages: %v", err) } + return messagesByID, nil } @@ -194,15 +218,18 @@ func (s *SQLite) GetMessageByIDUtil(ID string) (mmessage.Message, error) { defer dbLock.Unlock() var messageByte []byte + err := s.database.QueryRow(selectMessage, ID).Scan(&messageByte) if err != nil { return mmessage.Message{}, poperrors.NewDatabaseSelectErrorMsg(err.Error()) } var msg mmessage.Message + if err = json.Unmarshal(messageByte, &msg); err != nil { return mmessage.Message{}, poperrors.NewJsonUnmarshalError(err.Error()) } + return msg, nil } @@ -211,10 +238,10 @@ func (s *SQLite) StoreChannelUtil(channelPath, channelType, laoPath string) erro defer dbLock.Unlock() _, err := s.database.Exec(insertChannel, channelPath, channelTypeToID[channelType], laoPath) - if err != nil { return poperrors.NewDatabaseInsertErrorMsg("channel %s: %v", channelPath, err) } + return nil } @@ -226,5 +253,6 @@ func (s *SQLite) StorePubKeyUtil(keyPath string, key []byte) error { if err != nil { return poperrors.NewDatabaseInsertErrorMsg("key %s: %v", keyPath, err) } + return nil } diff --git a/be1-go/internal/database/sqlite/sqlite_init.go b/be1-go/internal/database/sqlite/sqlite_init.go index 6e84d43d83..448f2fdd9a 100644 --- a/be1-go/internal/database/sqlite/sqlite_init.go +++ b/be1-go/internal/database/sqlite/sqlite_init.go @@ -47,6 +47,7 @@ func NewSQLite(path string, foreignKeyOn bool, log zerolog.Logger) (SQLite, erro db.Close() return SQLite{}, poperrors.NewDatabaseTransactionBeginErrorMsg("%v", err) } + defer tx.Rollback() _, err = tx.Exec(createMessage) @@ -142,6 +143,7 @@ func (s *SQLite) Close() error { if err != nil { return poperrors.NewDatabaseInternalErrorMsg("close connection: %v", err) } + return nil } @@ -153,12 +155,14 @@ func (s *SQLite) StoreServerKeys(serverPubKey kyber.Point, serverSecretKey kyber if err != nil { return poperrors.NewDatabaseTransactionBeginErrorMsg("%v", err) } + defer tx.Rollback() serverPubBuf, err := serverPubKey.MarshalBinary() if err != nil { return poperrors.NewKeyMarshalError("server public key: %v", err) } + serverSecBuf, err := serverSecretKey.MarshalBinary() if err != nil { return poperrors.NewKeyMarshalError("server secret key: %v", err) @@ -166,6 +170,7 @@ func (s *SQLite) StoreServerKeys(serverPubKey kyber.Point, serverSecretKey kyber _, err = tx.Exec(insertKeys, serverKeysPath, base64.URLEncoding.EncodeToString(serverPubBuf), base64.URLEncoding.EncodeToString(serverSecBuf)) + if err != nil { return poperrors.NewDatabaseInsertErrorMsg("server keys: %v", err) } @@ -174,6 +179,7 @@ func (s *SQLite) StoreServerKeys(serverPubKey kyber.Point, serverSecretKey kyber if err != nil { return poperrors.NewDatabaseTransactionCommitErrorMsg("%v", err) } + return nil } @@ -185,15 +191,20 @@ func (s *SQLite) StoreFirstRumor() error { if err != nil { return poperrors.NewDatabaseTransactionBeginErrorMsg(err.Error()) } + var serverPubKey string + err = tx.QueryRow(selectPublicKey, serverKeysPath).Scan(&serverPubKey) if err != nil { return poperrors.NewDatabaseSelectErrorMsg("server keys: %v", err) } timestamp := make(mrumor.RumorTimestamp) + timestamp[serverPubKey] = 0 + timestampBuf, err := json.Marshal(timestamp) + if err != nil { return poperrors.NewJsonMarshalError("rumor timestamp: %v", err) } @@ -213,6 +224,7 @@ func fillChannelTypes(tx *sql.Tx) error { return poperrors.NewDatabaseInsertErrorMsg("channelType %s: %v", channelType, err) } } + return nil } @@ -224,14 +236,18 @@ func (s *SQLite) GetAllChannels() ([]string, error) { if err != nil { return nil, poperrors.NewDatabaseSelectErrorMsg("all channels: %v", err) } + defer rows.Close() var channels []string + for rows.Next() { var channelPath string + if err = rows.Scan(&channelPath); err != nil { return nil, poperrors.NewDatabaseScanErrorMsg("channel: %v", err) } + channels = append(channels, channelPath) } diff --git a/be1-go/internal/handler/channel/root/hroot/root.go b/be1-go/internal/handler/channel/root/hroot/root.go index ae35640fb3..c93fd00666 100644 --- a/be1-go/internal/handler/channel/root/hroot/root.go +++ b/be1-go/internal/handler/channel/root/hroot/root.go @@ -102,9 +102,7 @@ func (h *Handler) handleLaoCreate(msg mmessage.Message) error { return err } - laoPath := channel.RootPrefix + laoCreate.ID - - organizerPubBuf, err := h.verifyLaoCreation(msg, laoCreate, laoPath) + organizerPubBuf, laoPath, err := h.verifyLaoCreation(msg, laoCreate) if err != nil { return err } @@ -117,44 +115,46 @@ func (h *Handler) handleLaoCreate(msg mmessage.Message) error { return h.createLaoAndChannels(msg, laoGreetMsg, organizerPubBuf, laoPath) } -func (h *Handler) verifyLaoCreation(msg mmessage.Message, laoCreate mroot.LaoCreate, laoPath string) ([]byte, error) { +func (h *Handler) verifyLaoCreation(msg mmessage.Message, laoCreate mroot.LaoCreate) ([]byte, string, error) { + + laoPath := channel.RootPrefix + laoCreate.ID ok, err := h.db.HasChannel(laoPath) if err != nil { - return nil, err + return nil, "", err } else if ok { - return nil, errors.NewDuplicateResourceError("duplicate lao path: %s", laoPath) + return nil, "", errors.NewDuplicateResourceError("duplicate lao path: %s", laoPath) } err = laoCreate.Verify() if err != nil { - return nil, err + return nil, "", err } senderPubBuf, err := base64.URLEncoding.DecodeString(msg.Sender) if err != nil { - return nil, errors.NewInvalidMessageFieldError("failed to decode public key of the sender: %v", err) + return nil, "", errors.NewInvalidMessageFieldError("failed to decode public key of the sender: %v", err) } senderPubKey := crypto.Suite.Point() err = senderPubKey.UnmarshalBinary(senderPubBuf) if err != nil { - return nil, errors.NewInvalidMessageFieldError("failed to unmarshal public key of the sender: %v", err) + return nil, "", errors.NewInvalidMessageFieldError("failed to unmarshal public key of the sender: %v", err) } organizerPubBuf, err := base64.URLEncoding.DecodeString(laoCreate.Organizer) if err != nil { - return nil, errors.NewInvalidMessageFieldError("failed to decode public key of the organizer: %v", err) + return nil, "", errors.NewInvalidMessageFieldError("failed to decode public key of the organizer: %v", err) } organizerPubKey := crypto.Suite.Point() err = organizerPubKey.UnmarshalBinary(organizerPubBuf) if err != nil { - return nil, errors.NewInvalidMessageFieldError("failed to unmarshal public key of the organizer: %v", err) + return nil, "", errors.NewInvalidMessageFieldError("failed to unmarshal public key of the organizer: %v", err) } // Check if the sender and organizer fields of the create#lao message are equal if !organizerPubKey.Equal(senderPubKey) { - return nil, errors.NewAccessDeniedError("sender's public key does not match the organizer public key: %s != %s", + return nil, "", errors.NewAccessDeniedError("sender's public key does not match the organizer public key: %s != %s", senderPubKey, organizerPubKey) } @@ -162,11 +162,11 @@ func (h *Handler) verifyLaoCreation(msg mmessage.Message, laoCreate mroot.LaoCre // Check if the sender of the LAO creation message is the owner if ownerPublicKey != nil && !ownerPublicKey.Equal(senderPubKey) { - return nil, errors.NewAccessDeniedError("sender's public key does not match the owner public key: %s != %s", + return nil, "", errors.NewAccessDeniedError("sender's public key does not match the owner public key: %s != %s", senderPubKey, ownerPublicKey) } - return organizerPubBuf, nil + return organizerPubBuf, laoPath, nil } func (h *Handler) createLaoAndChannels(msg, laoGreetMsg mmessage.Message, organizerPubBuf []byte, laoPath string) error {