diff --git a/nucypher/config/base.py b/nucypher/config/base.py index 30f28e6ad..86038bd57 100644 --- a/nucypher/config/base.py +++ b/nucypher/config/base.py @@ -2,6 +2,10 @@ import json import os from abc import ABC, abstractmethod +from constant_sorrow.constants import ( + UNKNOWN_VERSION +) + from nucypher.config import constants @@ -70,6 +74,8 @@ class BaseConfiguration(ABC): INDENTATION = 2 DEFAULT_CONFIG_ROOT = constants.DEFAULT_CONFIG_ROOT + VERSION = NotImplemented + class ConfigurationError(RuntimeError): pass @@ -79,6 +85,9 @@ class BaseConfiguration(ABC): class NoConfigurationRoot(InvalidConfiguration): pass + class OldVersion(InvalidConfiguration): + pass + def __init__(self, config_root: str = None, filepath: str = None, @@ -220,11 +229,17 @@ class BaseConfiguration(ABC): def serialize(self, serializer=json.dumps) -> str: """Returns the JSON serialized output of `static_payload`""" - serialized_payload = serializer(self.static_payload(), indent=self.INDENTATION) + payload = self.static_payload() + payload['version'] = self.VERSION + serialized_payload = serializer(payload, indent=self.INDENTATION) return serialized_payload @classmethod def deserialize(cls, payload: str, deserializer=json.loads) -> dict: """Returns the JSON deserialized content of `payload`""" deserialized_payload = deserializer(payload) + version = deserialized_payload.pop('version', UNKNOWN_VERSION) + if version != cls.VERSION: + raise cls.OldVersion(f"Configuration file is the wrong version " + f"Expected version {cls.VERSION}; Got version {version}") return deserialized_payload diff --git a/nucypher/config/node.py b/nucypher/config/node.py index da3b26c0a..056a2c431 100644 --- a/nucypher/config/node.py +++ b/nucypher/config/node.py @@ -45,6 +45,8 @@ class CharacterConfiguration(BaseConfiguration): 'Sideways Engagement' of Character classes; a reflection of input parameters. """ + VERSION = 1 # bump when static payload scheme changes + CHARACTER_CLASS = NotImplemented DEFAULT_CONTROLLER_PORT = NotImplemented DEFAULT_DOMAIN = 'goerli' @@ -284,7 +286,6 @@ class CharacterConfiguration(BaseConfiguration): """ Warning: This method allows mutation and may result in an inconsistent configuration. """ - payload = cls._read_configuration_file(filepath=filepath) node_storage = cls.load_node_storage(storage_payload=payload['node_storage'], federated_only=payload['federated_only']) @@ -310,8 +311,7 @@ class CharacterConfiguration(BaseConfiguration): try: node_configuration = cls(filepath=filepath, provider_process=provider_process, **assembled_params) except TypeError as e: - # TODO: Trigger configuration migration? - raise cls.ConfigurationError(f"Your configuration file may be out of date: {e}") + raise cls.ConfigurationError(e) return node_configuration def validate(self) -> bool: