// generateKeys generates a set of keys and saves them to disk. func generateKeys(requiredKeys int, totalKeys int, folder string, keyname string) (types.UnlockConditions, error) { // Check that the inputs have sane values. if requiredKeys < 1 { return types.UnlockConditions{}, ErrInsecureAddress } if totalKeys < requiredKeys { return types.UnlockConditions{}, ErrUnspendableAddress } // Generate 'TotalKeys', filling out everything except the unlock // conditions. keys := make([]KeyPair, totalKeys) pubKeys := make([]crypto.PublicKey, totalKeys) for i := range keys { var err error keys[i].Header = FileHeader keys[i].Version = FileVersion keys[i].Index = i keys[i].SecretKey, pubKeys[i], err = crypto.GenerateSignatureKeys() if err != nil { return types.UnlockConditions{}, err } } // Generate the unlock conditions and add them to each KeyPair object. This // must be done second because the keypairs can't be given unlock // conditions until the PublicKeys have all been added. unlockConditions := types.UnlockConditions{ Timelock: 0, SignaturesRequired: uint64(requiredKeys), } for i := range keys { unlockConditions.PublicKeys = append(unlockConditions.PublicKeys, types.SiaPublicKey{ Algorithm: types.SignatureEd25519, Key: pubKeys[i][:], }) } for i := range keys { keys[i].UnlockConditions = unlockConditions } // Save the KeyPairs to disk. if folder != "" { err := os.MkdirAll(folder, 0700) if err != nil { return types.UnlockConditions{}, err } } for i, key := range keys { keyFilename := filepath.Join(folder, keyname+"_Key"+strconv.Itoa(i)+FileExtension) _, err := os.Stat(keyFilename) if !os.IsNotExist(err) { if err != nil { return types.UnlockConditions{}, err } return types.UnlockConditions{}, ErrOverwrite } err = encoding.WriteFile(keyFilename, key) if err != nil { return types.UnlockConditions{}, err } } return unlockConditions, nil }