data_handler.go 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. package extension
  2. import (
  3. "encoding/json"
  4. "io/ioutil"
  5. "os"
  6. "path/filepath"
  7. "github.com/ethereum/go-ethereum/common"
  8. "github.com/ethereum/go-ethereum/core/types"
  9. "github.com/ethereum/go-ethereum/log"
  10. )
  11. /*
  12. The file can have two formats:
  13. 1.
  14. {
  15. "psiContracts": {
  16. "psi1": {
  17. "contract1address": ...,
  18. "contract2address": ...,
  19. },
  20. ...
  21. }
  22. }
  23. 2.
  24. {
  25. "contract1address": ...,
  26. "contract2address": ...,
  27. }
  28. */
  29. const extensionContractData = "activeExtensions.json"
  30. type DataHandler interface {
  31. Load() (map[types.PrivateStateIdentifier]map[common.Address]*ExtensionContract, error)
  32. Save(extensionContracts map[types.PrivateStateIdentifier]map[common.Address]*ExtensionContract) error
  33. }
  34. type JsonFileDataHandler struct {
  35. saveFile string
  36. }
  37. func NewJsonFileDataHandler(dataDirectory string) *JsonFileDataHandler {
  38. return &JsonFileDataHandler{
  39. saveFile: filepath.Join(dataDirectory, extensionContractData),
  40. }
  41. }
  42. /*
  43. The strategy when loading the save file is too check if the newer "psiContracts" field is present.
  44. If so, then everything should exist under that key, and so we can unmarshal and return immediately.
  45. If not, then the save file was made from a previous version. Load up all the data as before and
  46. put it under the "private" PSI.
  47. It should never be the case the file contains both types of data at once.
  48. */
  49. func (handler *JsonFileDataHandler) Load() (map[types.PrivateStateIdentifier]map[common.Address]*ExtensionContract, error) {
  50. if _, err := os.Stat(handler.saveFile); !(err == nil || !os.IsNotExist(err)) {
  51. return map[types.PrivateStateIdentifier]map[common.Address]*ExtensionContract{types.DefaultPrivateStateIdentifier: {}}, nil
  52. }
  53. blob, err := ioutil.ReadFile(handler.saveFile)
  54. if err != nil {
  55. return nil, err
  56. }
  57. var untyped map[string]json.RawMessage
  58. if err := json.Unmarshal(blob, &untyped); err != nil {
  59. return nil, err
  60. }
  61. if psiContracts, ok := untyped["psiContracts"]; ok {
  62. var contracts map[types.PrivateStateIdentifier]map[common.Address]*ExtensionContract
  63. json.Unmarshal(psiContracts, &contracts)
  64. return contracts, nil
  65. }
  66. currentContracts := make(map[common.Address]*ExtensionContract)
  67. for key, val := range untyped {
  68. extAddress := common.HexToAddress(key)
  69. var ext ExtensionContract
  70. json.Unmarshal(val, &ext)
  71. currentContracts[extAddress] = &ext
  72. }
  73. return map[types.PrivateStateIdentifier]map[common.Address]*ExtensionContract{types.DefaultPrivateStateIdentifier: currentContracts}, nil
  74. }
  75. func (handler *JsonFileDataHandler) Save(extensionContracts map[types.PrivateStateIdentifier]map[common.Address]*ExtensionContract) error {
  76. //we want to put the map under "psiContracts" key to distinguish from existing data
  77. saveData := make(map[string]interface{})
  78. saveData["psiContracts"] = extensionContracts
  79. //no unmarshallable types, so can't error
  80. output, _ := json.Marshal(&saveData)
  81. if errSaving := ioutil.WriteFile(handler.saveFile, output, 0644); errSaving != nil {
  82. log.Error("Couldn't save outstanding extension contract details")
  83. return errSaving
  84. }
  85. return nil
  86. }