gitlab.com/SiaPrime/SiaPrime@v1.4.1/modules/renter/contractor/persist.go (about) 1 package contractor 2 3 import ( 4 "os" 5 "path/filepath" 6 "reflect" 7 8 "gitlab.com/SiaPrime/SiaPrime/modules" 9 "gitlab.com/SiaPrime/SiaPrime/modules/renter/proto" 10 "gitlab.com/SiaPrime/SiaPrime/persist" 11 "gitlab.com/SiaPrime/SiaPrime/types" 12 13 "gitlab.com/NebulousLabs/errors" 14 ) 15 16 // contractorPersist defines what Contractor data persists across sessions. 17 type contractorPersist struct { 18 Allowance modules.Allowance `json:"allowance"` 19 BlockHeight types.BlockHeight `json:"blockheight"` 20 CurrentPeriod types.BlockHeight `json:"currentperiod"` 21 LastChange modules.ConsensusChangeID `json:"lastchange"` 22 RecentRecoveryChange modules.ConsensusChangeID `json:"recentrecoverychange"` 23 OldContracts []modules.RenterContract `json:"oldcontracts"` 24 RecoverableContracts []modules.RecoverableContract `json:"recoverablecontracts"` 25 RenewedFrom map[string]types.FileContractID `json:"renewedfrom"` 26 RenewedTo map[string]types.FileContractID `json:"renewedto"` 27 } 28 29 // persistData returns the data in the Contractor that will be saved to disk. 30 func (c *Contractor) persistData() contractorPersist { 31 data := contractorPersist{ 32 Allowance: c.allowance, 33 BlockHeight: c.blockHeight, 34 CurrentPeriod: c.currentPeriod, 35 LastChange: c.lastChange, 36 RecentRecoveryChange: c.recentRecoveryChange, 37 RenewedFrom: make(map[string]types.FileContractID), 38 RenewedTo: make(map[string]types.FileContractID), 39 } 40 for k, v := range c.renewedFrom { 41 data.RenewedFrom[k.String()] = v 42 } 43 for k, v := range c.renewedTo { 44 data.RenewedTo[k.String()] = v 45 } 46 for _, contract := range c.oldContracts { 47 data.OldContracts = append(data.OldContracts, contract) 48 } 49 for _, contract := range c.recoverableContracts { 50 data.RecoverableContracts = append(data.RecoverableContracts, contract) 51 } 52 return data 53 } 54 55 // load loads the Contractor persistence data from disk. 56 func (c *Contractor) load() error { 57 var data contractorPersist 58 err := c.persist.load(&data) 59 if err != nil { 60 return err 61 } 62 63 // COMPATv136 if the allowance is not the empty allowance and "Expected" 64 // fields are not set, set them to the default values. 65 if !reflect.DeepEqual(data.Allowance, modules.Allowance{}) { 66 if data.Allowance.ExpectedStorage == 0 && data.Allowance.ExpectedUpload == 0 && 67 data.Allowance.ExpectedDownload == 0 && data.Allowance.ExpectedRedundancy == 0 { 68 // Set the fields to the defaults. 69 data.Allowance.ExpectedStorage = modules.DefaultAllowance.ExpectedStorage 70 data.Allowance.ExpectedUpload = modules.DefaultAllowance.ExpectedUpload 71 data.Allowance.ExpectedDownload = modules.DefaultAllowance.ExpectedDownload 72 data.Allowance.ExpectedRedundancy = modules.DefaultAllowance.ExpectedRedundancy 73 } 74 } 75 76 c.allowance = data.Allowance 77 c.blockHeight = data.BlockHeight 78 c.currentPeriod = data.CurrentPeriod 79 c.lastChange = data.LastChange 80 c.recentRecoveryChange = data.RecentRecoveryChange 81 var fcid types.FileContractID 82 for k, v := range data.RenewedFrom { 83 if err := fcid.LoadString(k); err != nil { 84 return err 85 } 86 c.renewedFrom[fcid] = v 87 } 88 for k, v := range data.RenewedTo { 89 if err := fcid.LoadString(k); err != nil { 90 return err 91 } 92 c.renewedTo[fcid] = v 93 } 94 for _, contract := range data.OldContracts { 95 c.oldContracts[contract.ID] = contract 96 } 97 for _, contract := range data.RecoverableContracts { 98 c.recoverableContracts[contract.ID] = contract 99 } 100 101 return nil 102 } 103 104 // save saves the Contractor persistence data to disk. 105 func (c *Contractor) save() error { 106 return c.persist.save(c.persistData()) 107 } 108 109 // convertPersist converts the pre-v1.3.1 contractor persist formats to the new 110 // formats. 111 func convertPersist(dir string) error { 112 // Try loading v1.3.1 persist. If it has the correct version number, no 113 // further action is necessary. 114 persistPath := filepath.Join(dir, "contractor.json") 115 err := persist.LoadJSON(persistMeta, nil, persistPath) 116 if err == nil { 117 return nil 118 } 119 120 // Try loading v1.3.0 persist (journal). 121 journalPath := filepath.Join(dir, "contractor.journal") 122 if _, err := os.Stat(journalPath); os.IsNotExist(err) { 123 // no journal file found; assume this is a fresh install 124 return nil 125 } 126 var p journalPersist 127 j, err := openJournal(journalPath, &p) 128 if err != nil { 129 return err 130 } 131 j.Close() 132 // convert to v1.3.1 format and save 133 data := contractorPersist{ 134 Allowance: p.Allowance, 135 BlockHeight: p.BlockHeight, 136 CurrentPeriod: p.CurrentPeriod, 137 LastChange: p.LastChange, 138 } 139 for _, c := range p.OldContracts { 140 data.OldContracts = append(data.OldContracts, modules.RenterContract{ 141 ID: c.ID, 142 HostPublicKey: c.HostPublicKey, 143 StartHeight: c.StartHeight, 144 EndHeight: c.EndHeight(), 145 RenterFunds: c.RenterFunds(), 146 DownloadSpending: c.DownloadSpending, 147 StorageSpending: c.StorageSpending, 148 UploadSpending: c.UploadSpending, 149 TotalCost: c.TotalCost, 150 ContractFee: c.ContractFee, 151 TxnFee: c.TxnFee, 152 SiafundFee: c.SiafundFee, 153 }) 154 } 155 err = persist.SaveJSON(persistMeta, data, persistPath) 156 if err != nil { 157 return err 158 } 159 160 // create the contracts directory if it does not yet exist 161 cs, err := proto.NewContractSet(filepath.Join(dir, "contracts"), modules.ProdDependencies) 162 if err != nil { 163 return err 164 } 165 defer cs.Close() 166 167 // convert contracts to contract files 168 for _, c := range p.Contracts { 169 cachedRev := p.CachedRevisions[c.ID.String()] 170 if err := cs.ConvertV130Contract(c, cachedRev); err != nil { 171 return err 172 } 173 } 174 175 // delete the journal file 176 return errors.AddContext(os.Remove(journalPath), "failed to remove journal file") 177 }