267 lines
10 KiB
Go
267 lines
10 KiB
Go
|
|
// parametersStorage provides functions to store and retrieve network parameters
|
|
|
|
package parametersStorage
|
|
|
|
//TODO: Create a job to prune old parameters
|
|
|
|
import "seekia/internal/parameters/readParameters"
|
|
import "seekia/internal/helpers"
|
|
import "seekia/internal/localFilesystem"
|
|
import "seekia/internal/encoding"
|
|
|
|
import "bytes"
|
|
import goFilepath "path/filepath"
|
|
import "strings"
|
|
import "errors"
|
|
import "slices"
|
|
|
|
|
|
//TODO: The key of the master admin who can change the admin permissions
|
|
const masterAdminPublicKey string = "TODO"
|
|
|
|
//Outputs:
|
|
// -bool: Parameters to add are well formed
|
|
// -bool: Admin permissions found (we cannot add parameters without these)
|
|
// -error
|
|
func AddParameters(inputParameters []byte)(bool, bool, error){
|
|
|
|
ableToRead, _, parametersNetworkType, listOfAdmins, parametersType, parametersCreationTime, _, err := readParameters.ReadParameters(true, inputParameters)
|
|
if (err != nil) { return false, false, err }
|
|
if (ableToRead == false){
|
|
return false, false, nil
|
|
}
|
|
|
|
adminParametersFound, parametersAreAuthorized, err := verifyParametersAreAuthorized(parametersType, parametersNetworkType, parametersCreationTime, listOfAdmins)
|
|
if (err != nil) { return false, false, err }
|
|
if (adminParametersFound == false){
|
|
// We do not have admin parameters. We cannot determine if parameters to add are authorized
|
|
return false, false, nil
|
|
}
|
|
if (parametersAreAuthorized == false){
|
|
// Parameters are not authorized.
|
|
// Could be malicious host who sent parameters, or admin permissions were updated and we/they do not have them yet
|
|
return true, true, nil
|
|
}
|
|
|
|
// We check if parameters already exist that are newer
|
|
|
|
parametersFound, _, _, existingParametersCreationTime, err := GetAuthorizedParameters(parametersType, parametersNetworkType)
|
|
if (err != nil) { return false, false, err }
|
|
if (parametersFound == true){
|
|
if (existingParametersCreationTime >= parametersCreationTime){
|
|
// These parameters are older than our existing stored authorized parameters.
|
|
// We will not add them.
|
|
return true, true, nil
|
|
}
|
|
}
|
|
|
|
seekiaDirectory, err := localFilesystem.GetSeekiaDataFolderPath()
|
|
if (err != nil) { return false, false, err }
|
|
|
|
networkTypeString := helpers.ConvertByteToString(parametersNetworkType)
|
|
|
|
networkTypeFoldername := "Network" + networkTypeString
|
|
|
|
parametersFolderpath := goFilepath.Join(seekiaDirectory, "Parameters", networkTypeFoldername)
|
|
parametersFilename := parametersType + ".messagepack"
|
|
|
|
err = localFilesystem.CreateOrOverwriteFile(inputParameters, parametersFolderpath, parametersFilename)
|
|
if (err != nil) { return false, false, err }
|
|
|
|
return true, true, nil
|
|
}
|
|
|
|
|
|
// This function will return parameters that are signed by known admins
|
|
//Outputs:
|
|
// -bool: Requested parameters found and signed by valid admins
|
|
// -[]byte: Parameters bytes
|
|
// -map[string]string: Parameters map
|
|
// -int64: Parameters creation time
|
|
// -error
|
|
func GetAuthorizedParameters(parametersType string, networkType byte)(bool, []byte, map[string]string, int64, error){
|
|
|
|
isValid := readParameters.VerifyParametersType(parametersType)
|
|
if (isValid == false) {
|
|
return false, nil, nil, 0, errors.New("GetAuthorizedParameters called with invalid parametersType: " + parametersType)
|
|
}
|
|
|
|
isValid = helpers.VerifyNetworkType(networkType)
|
|
if (isValid == false){
|
|
networkTypeString := helpers.ConvertByteToString(networkType)
|
|
return false, nil, nil, 0, errors.New("GetAuthorizedParameters called with invalid networkType: " + networkTypeString)
|
|
}
|
|
|
|
parametersExist, storedParametersBytes, err := getStoredParameters(parametersType, networkType)
|
|
if (err != nil) { return false, nil, nil, 0, err }
|
|
if (parametersExist == false){
|
|
return false, nil, nil, 0, nil
|
|
}
|
|
|
|
ableToRead, _, parametersNetworkType, listOfSigners, currentParametersType, parametersCreationTime, parametersMap, err := readParameters.ReadParameters(true, storedParametersBytes)
|
|
if (err != nil) { return false, nil, nil, 0, err }
|
|
if (ableToRead == false) {
|
|
return false, nil, nil, 0, errors.New("Stored parameters are corrupt: storing corrupt " + parametersType + "parameter.")
|
|
}
|
|
if (parametersNetworkType != networkType){
|
|
return false, nil, nil, 0, errors.New("getStoredParameters returning different networkType parameters")
|
|
}
|
|
if (currentParametersType != parametersType){
|
|
return false, nil, nil, 0, errors.New("getStoredParameters returning different parametersType parameters")
|
|
}
|
|
|
|
adminPermissionsFound, parametersAreAuthorized, err := verifyParametersAreAuthorized(parametersType, networkType, parametersCreationTime, listOfSigners)
|
|
if (err != nil) { return false, nil, nil, 0, err }
|
|
if (adminPermissionsFound == false || parametersAreAuthorized == false){
|
|
return false, nil, nil, 0, nil
|
|
}
|
|
|
|
return true, storedParametersBytes, parametersMap, parametersCreationTime, nil
|
|
}
|
|
|
|
//Outputs:
|
|
// -bool: Admin permissions found
|
|
// -bool: Parameters are authorized
|
|
// -error
|
|
func verifyParametersAreAuthorized(parametersType string, networkType byte, parametersCreationTime int64, parametersSigners [][32]byte)(bool, bool, error){
|
|
|
|
containsDuplicates, _ := helpers.CheckIfListContainsDuplicates(parametersSigners)
|
|
if (containsDuplicates == true){
|
|
return false, false, errors.New("verifyParametersAreAuthorized called with parametersSigners list containing duplicates.")
|
|
}
|
|
|
|
parametersExist, adminPermissionsParameters, err := getStoredParameters("AdminPermissions", networkType)
|
|
if (err != nil) { return false, false, err }
|
|
if (parametersExist == false){
|
|
return false, false, nil
|
|
}
|
|
|
|
ableToRead, _, parametersNetworkType, listOfAdmins, currentParametersType, _, adminPermissionsMap, err := readParameters.ReadParameters(true, adminPermissionsParameters)
|
|
if (err != nil) { return false, false, err }
|
|
if (ableToRead == false){
|
|
return false, false, errors.New("Parameters storage corrupt: Storing invalid AdminPermissions.")
|
|
}
|
|
if (parametersNetworkType != networkType){
|
|
return false, false, errors.New("getStoredParameters returning parameters of a different networkType")
|
|
}
|
|
if (currentParametersType != "AdminPermissions"){
|
|
return false, false, errors.New("getStoredParameters returning parameters of a different parametersType")
|
|
}
|
|
if (len(listOfAdmins) != 1){
|
|
return false, false, errors.New("Parameters storage is corrupt: storing AdminPermissions with more than 1 signer.")
|
|
}
|
|
|
|
masterAdminPublicKeyBytes, err := encoding.DecodeHexStringToBytes(masterAdminPublicKey)
|
|
if (err != nil){
|
|
return false, false, errors.New("Master admin public key is malformed: " + masterAdminPublicKey + ". Reason: " + err.Error())
|
|
}
|
|
|
|
areEqual := bytes.Equal(listOfAdmins[0][:], masterAdminPublicKeyBytes)
|
|
if (areEqual == false){
|
|
return false, false, errors.New("Parameters storage is corrupt: storing AdminPermissions with different admin key.")
|
|
}
|
|
|
|
authorizedAdminsListString, exists := adminPermissionsMap[parametersType + "_AuthorizedAdmins"]
|
|
if (exists == false) {
|
|
return false, false, errors.New("Stored AdminPermissions parameters missing " + parametersType + "_AuthorizedAdmins")
|
|
}
|
|
|
|
authorizedAdminsList := strings.Split(authorizedAdminsListString, "+")
|
|
if (len(authorizedAdminsList) == 0){
|
|
return false, false, errors.New("Stored AdminPermissions parameters contains empty authorizedAdmins list")
|
|
}
|
|
|
|
authorizedAdminKeysList := make([][32]byte, 0, len(authorizedAdminsList))
|
|
|
|
for _, adminPublicKeyHex := range authorizedAdminsList{
|
|
|
|
adminPublicKey, err := encoding.DecodeHexStringToBytes(adminPublicKeyHex)
|
|
if (err != nil){
|
|
return false, false, errors.New("Stored AdminPermissions parameters contains empty authorizedAdmins list: Key not hex.")
|
|
}
|
|
|
|
if (len(adminPublicKey) != 32){
|
|
return false, false, errors.New("Stored AdminPermissions parameters contains empty authorizedAdmins list: Key is invalid length.")
|
|
}
|
|
|
|
adminPublicKeyArray := [32]byte(adminPublicKey)
|
|
|
|
authorizedAdminKeysList = append(authorizedAdminKeysList, adminPublicKeyArray)
|
|
}
|
|
|
|
minimumSigners, exists := adminPermissionsMap[parametersType + "_MinimumSigners"]
|
|
if (exists == false) {
|
|
return false, false, errors.New("Parameters storage is corrupt: AdminPermissions missing MinimumSigners but contains AuthorizedAdmins")
|
|
}
|
|
|
|
minimumNumberOfSigners, err := helpers.ConvertStringToInt(minimumSigners)
|
|
if (err != nil) {
|
|
return false, false, errors.New("Parameters storage is corrupt: AdminPermissions contains invalid minimumSigners: " + minimumSigners)
|
|
}
|
|
|
|
if (len(authorizedAdminKeysList) < minimumNumberOfSigners){
|
|
return false, false, errors.New("Parameters storage is corrupt: AdminPermissions contains less authorizedAdmins than minimumSigners")
|
|
}
|
|
|
|
minimumCreationTime, exists := adminPermissionsMap[parametersType + "_MinimumCreationTime"]
|
|
if (exists == false) {
|
|
return false, false, errors.New("Parameters storage is corrupt: AdminPermissions missing minimumCreationTime but contains AuthorizedAdmins for parameterType.")
|
|
}
|
|
|
|
minimumCreationTimeInt64, err := helpers.ConvertStringToInt64(minimumCreationTime)
|
|
if (err != nil) {
|
|
return false, false, errors.New("Parameters storage is corrupt: AdminPermissions contains invalid minimumCreationTime: " + minimumCreationTime)
|
|
}
|
|
|
|
if (parametersCreationTime < minimumCreationTimeInt64){
|
|
return false, false, nil
|
|
}
|
|
|
|
verifiedAdminsCount := 0
|
|
|
|
for _, adminPublicKey := range parametersSigners{
|
|
|
|
isInList := slices.Contains(authorizedAdminKeysList, adminPublicKey)
|
|
if (isInList == true){
|
|
verifiedAdminsCount += 1
|
|
}
|
|
}
|
|
|
|
if (verifiedAdminsCount < minimumNumberOfSigners){
|
|
// This parameters file does not have enough authorized signers
|
|
// Either the provider of the parameters file is malicious, or the permissions file has updated
|
|
// and the provider/we have not received the newest file
|
|
return true, false, nil
|
|
}
|
|
|
|
return true, true, nil
|
|
}
|
|
|
|
//Outputs:
|
|
// -bool: Parameters exist
|
|
// -[]byte: Parameters bytes
|
|
// -error
|
|
func getStoredParameters(parametersType string, networkType byte)(bool, []byte, error){
|
|
|
|
seekiaDirectory, err := localFilesystem.GetSeekiaDataFolderPath()
|
|
if (err != nil) { return false, nil, err }
|
|
|
|
networkTypeString := helpers.ConvertByteToString(networkType)
|
|
|
|
networkTypeFoldername := "Network" + networkTypeString
|
|
|
|
parametersFilename := parametersType + ".messagepack"
|
|
parametersFilepath := goFilepath.Join(seekiaDirectory, "Parameters", networkTypeFoldername, parametersFilename)
|
|
|
|
exists, fileBytes, err := localFilesystem.GetFileContents(parametersFilepath)
|
|
if (err != nil) { return false, nil, err }
|
|
if (exists == false){
|
|
return false, nil, nil
|
|
}
|
|
|
|
return true, fileBytes, nil
|
|
}
|
|
|
|
|
|
|