// addRandFolder connects a storage folder to a random directory in the // tester's persist dir. func (smt *storageManagerTester) addRandFolder(size uint64) error { dir := filepath.Join(smt.persistDir, persist.RandomSuffix()) err := os.Mkdir(dir, 0700) if err != nil { return err } return smt.sm.AddStorageFolder(dir, size) }
// reloadedServerTester creates a server tester where all of the persistent // data has been copied to a new folder and all of the modules re-initialized // on the new folder. This gives an opportunity to see how modules will behave // when they are relying on their persistent structures. func (st *serverTester) reloadedServerTester() (*serverTester, error) { // Copy the testing directory. copiedDir := st.dir + " - " + persist.RandomSuffix() err := build.CopyDir(st.dir, copiedDir) if err != nil { return nil, err } copyST, err := assembleServerTester(st.walletKey, copiedDir) if err != nil { return nil, err } return copyST, nil }
// reorgToBlank creates a bunch of empty blocks on top of the genesis block // that reorgs the explorer to a state of all blank blocks. func (et *explorerTester) reorgToBlank() error { // Get a unique directory name to house the persistence of the miner // dependencies. dir := et.testdir + " - " + persist.RandomSuffix() // Create a miner and all dependencies to create an alternate chain. g, err := gateway.New("localhost:0", false, filepath.Join(dir, modules.GatewayDir)) if err != nil { return err } cs, err := consensus.New(g, false, filepath.Join(dir, modules.ConsensusDir)) if err != nil { return err } tp, err := transactionpool.New(cs, g, filepath.Join(dir, modules.TransactionPoolDir)) if err != nil { return err } w, err := wallet.New(cs, tp, filepath.Join(dir, modules.WalletDir)) if err != nil { return err } key, err := crypto.GenerateTwofishKey() if err != nil { return err } _, err = w.Encrypt(key) if err != nil { return err } err = w.Unlock(key) if err != nil { return err } m, err := miner.New(cs, tp, w, filepath.Join(dir, modules.RenterDir)) if err != nil { return err } // Mine blocks until the height is higher than the existing consensus, // submitting each block to the explorerTester. currentHeight := cs.Height() for i := types.BlockHeight(0); i <= currentHeight+1; i++ { block, err := m.AddBlock() if err != nil { return err } et.cs.AcceptBlock(block) // error is not checked, will not always be nil } return nil }
// loadSiagKeys loads a set of siag keyfiles into the wallet, so that the // wallet may spend the siafunds. func (w *Wallet) loadSiagKeys(masterKey crypto.TwofishKey, keyfiles []string) error { // Load the keyfiles from disk. if len(keyfiles) < 1 { return ErrNoKeyfile } skps := make([]SiagKeyPair, len(keyfiles)) for i, keyfile := range keyfiles { err := encoding.ReadFile(keyfile, &skps[i]) if err != nil { return err } if skps[i].Header != SiagFileHeader { return ErrUnknownHeader } if skps[i].Version != SiagFileVersion { return ErrUnknownVersion } } // Check that all of the loaded files have the same address, and that there // are enough to create the transaction. baseUnlockHash := skps[0].UnlockConditions.UnlockHash() for _, skp := range skps { if skp.UnlockConditions.UnlockHash() != baseUnlockHash { return ErrInconsistentKeys } } if uint64(len(skps)) < skps[0].UnlockConditions.SignaturesRequired { return ErrInsufficientKeys } // Drop all unneeded keys. skps = skps[0:skps[0].UnlockConditions.SignaturesRequired] // Merge the keys into a single spendableKey and save it to the wallet. var sk spendableKey sk.UnlockConditions = skps[0].UnlockConditions for _, skp := range skps { sk.SecretKeys = append(sk.SecretKeys, skp.SecretKey) } err := w.loadSpendableKey(masterKey, sk) if err != nil { return err } err = w.saveSettingsSync() if err != nil { return err } return w.createBackup(filepath.Join(w.persistDir, "Sia Wallet Encrypted Backup - "+persist.RandomSuffix()+settingsFileSuffix)) }
// recoverSeed integrates a recovery seed into the wallet. func (w *Wallet) recoverSeed(masterKey crypto.TwofishKey, seed modules.Seed) error { // Check that the seed is not already known. for _, wSeed := range w.seeds { if seed == wSeed { return errKnownSeed } } // Encrypt the seed and save the seed file. var sfuid SeedFileUID _, err := rand.Read(sfuid[:]) if err != nil { return err } sek := seedFileEncryptionKey(masterKey, sfuid) plaintextVerification := make([]byte, encryptionVerificationLen) encryptionVerification, err := sek.EncryptBytes(plaintextVerification) if err != nil { return err } cryptSeed, err := sek.EncryptBytes(seed[:]) if err != nil { return err } seedFilename := filepath.Join(w.persistDir, seedFilePrefix+persist.RandomSuffix()+seedFileSuffix) seedFile := SeedFile{ SeedFileUID: sfuid, EncryptionVerification: encryptionVerification, Seed: cryptSeed, } err = persist.SaveFile(seedMetadata, seedFile, seedFilename) if err != nil { return err } // Add the seed file to the wallet's set of tracked seeds and save the // wallet settings. w.settings.AuxiliarySeedFiles = append(w.settings.AuxiliarySeedFiles, seedFile) err = w.saveSettings() if err != nil { return err } w.integrateSeed(seed) return nil }
// Load033xWallet loads a v0.3.3.x wallet as an unseeded key, such that the // funds become spendable to the current wallet. func (w *Wallet) Load033xWallet(masterKey crypto.TwofishKey, filepath033x string) error { if err := w.tg.Add(); err != nil { return err } defer w.tg.Done() w.mu.Lock() defer w.mu.Unlock() err := w.checkMasterKey(masterKey) if err != nil { return err } var savedKeys []SavedKey033x err = encoding.ReadFile(filepath033x, &savedKeys) if err != nil { return err } var seedsLoaded int for _, savedKey := range savedKeys { spendKey := spendableKey{ UnlockConditions: savedKey.UnlockConditions, SecretKeys: []crypto.SecretKey{savedKey.SecretKey}, } err = w.loadSpendableKey(masterKey, spendKey) if err != nil && err != errDuplicateSpendableKey { return err } if err == nil { seedsLoaded++ } } err = w.saveSettingsSync() if err != nil { return err } if seedsLoaded == 0 { return errAllDuplicates } return w.createBackup(filepath.Join(w.persistDir, "Sia Wallet Encrypted Backup - "+persist.RandomSuffix()+settingsFileSuffix)) }
// createSeed creates a wallet seed and encrypts it using a key derived from // the master key, then addds it to the wallet as the primary seed, while // making a disk backup. func (w *Wallet) createSeed(masterKey crypto.TwofishKey, seed modules.Seed) error { // Derive the key used to encrypt the seed file, and create the encryption // verification object. var sfuid SeedFileUID _, err := rand.Read(sfuid[:]) if err != nil { return err } sfek := seedFileEncryptionKey(masterKey, sfuid) plaintextVerification := make([]byte, encryptionVerificationLen) encryptionVerification, err := sfek.EncryptBytes(plaintextVerification) if err != nil { return err } // Encrypt the seed and save the seed file. seedName := seedFilePrefix + persist.RandomSuffix() + seedFileSuffix filename := filepath.Join(w.persistDir, seedName) cryptSeed, err := sfek.EncryptBytes(seed[:]) if err != nil { return err } w.primarySeed = seed w.settings.PrimarySeedFile = SeedFile{ SeedFileUID: sfuid, EncryptionVerification: encryptionVerification, Seed: cryptSeed, } w.settings.PrimarySeedProgress = 0 err = persist.SaveFile(seedMetadata, &w.settings.PrimarySeedFile, filename) if err != nil { return err } err = w.saveSettings() if err != nil { return err } return nil }
// encryptAndSaveSeedFile encrypts and saves a seed file. func (w *Wallet) encryptAndSaveSeedFile(masterKey crypto.TwofishKey, seed modules.Seed) (SeedFile, error) { var sf SeedFile _, err := rand.Read(sf.UID[:]) if err != nil { return SeedFile{}, err } sek := uidEncryptionKey(masterKey, sf.UID) plaintextVerification := make([]byte, encryptionVerificationLen) sf.EncryptionVerification, err = sek.EncryptBytes(plaintextVerification) if err != nil { return SeedFile{}, err } sf.Seed, err = sek.EncryptBytes(seed[:]) if err != nil { return SeedFile{}, err } seedFilename := filepath.Join(w.persistDir, seedFilePrefix+persist.RandomSuffix()+seedFileSuffix) err = persist.SaveFileSync(seedMetadata, sf, seedFilename) if err != nil { return SeedFile{}, err } return sf, nil }