// EmpowerSeries adds the given extended private key (in raw format) to the // series with the given ID, thus allowing it to sign deposit/withdrawal // scripts. The series with the given ID must exist, the key must be a valid // private extended key and must match one of the series' extended public keys. // // This method must be called with the Pool's manager unlocked. func (p *Pool) EmpowerSeries(seriesID uint32, rawPrivKey string) error { // make sure this series exists series := p.Series(seriesID) if series == nil { str := fmt.Sprintf("series %d does not exist for this voting pool", seriesID) return newError(ErrSeriesNotExists, str, nil) } // Check that the private key is valid. privKey, err := hdkeychain.NewKeyFromString(rawPrivKey) if err != nil { str := fmt.Sprintf("invalid extended private key %v", rawPrivKey) return newError(ErrKeyChain, str, err) } if !privKey.IsPrivate() { str := fmt.Sprintf( "to empower a series you need the extended private key, not an extended public key %v", privKey) return newError(ErrKeyIsPublic, str, err) } pubKey, err := privKey.Neuter() if err != nil { str := fmt.Sprintf("invalid extended private key %v, can't convert to public key", rawPrivKey) return newError(ErrKeyNeuter, str, err) } lookingFor := pubKey.String() found := false // Make sure the private key has the corresponding public key in the series, // to be able to empower it. for i, publicKey := range series.publicKeys { if publicKey.String() == lookingFor { found = true series.privateKeys[i] = privKey } } if !found { str := fmt.Sprintf( "private Key does not have a corresponding public key in this series") return newError(ErrKeysPrivatePublicMismatch, str, nil) } if err = p.saveSeriesToDisk(seriesID, series); err != nil { return err } return nil }
// decryptExtendedKey uses Manager.Decrypt() to decrypt the encrypted byte slice and return // an extended (public or private) key representing it. // // This method must be called with the Pool's manager unlocked. func (p *Pool) decryptExtendedKey(keyType waddrmgr.CryptoKeyType, encrypted []byte) (*hdkeychain.ExtendedKey, error) { decrypted, err := p.manager.Decrypt(keyType, encrypted) if err != nil { str := fmt.Sprintf("cannot decrypt key %v", encrypted) return nil, newError(ErrCrypto, str, err) } result, err := hdkeychain.NewKeyFromString(string(decrypted)) zero.Bytes(decrypted) if err != nil { str := fmt.Sprintf("cannot get key from string %v", decrypted) return nil, newError(ErrKeyChain, str, err) } return result, nil }
func createTestPubKeys(t *testing.T, number, offset int) []*hdkeychain.ExtendedKey { xpubRaw := "xpub661MyMwAqRbcFwdnYF5mvCBY54vaLdJf8c5ugJTp5p7PqF9J1USgBx12qYMnZ9yUiswV7smbQ1DSweMqu8wn7Jociz4PWkuJ6EPvoVEgMw7" xpubKey, err := hdkeychain.NewKeyFromString(xpubRaw) if err != nil { t.Fatalf("Failed to generate new key: %v", err) } keys := make([]*hdkeychain.ExtendedKey, number) for i := uint32(0); i < uint32(len(keys)); i++ { chPubKey, err := xpubKey.Child(i + uint32(offset)) if err != nil { t.Fatalf("Failed to generate child key: %v", err) } keys[i] = chPubKey } return keys }
// Convert the given slice of strings into a slice of ExtendedKeys, // checking that all of them are valid public (and not private) keys, // and that there are no duplicates. func convertAndValidatePubKeys(rawPubKeys []string) ([]*hdkeychain.ExtendedKey, error) { seenKeys := make(map[string]bool) keys := make([]*hdkeychain.ExtendedKey, len(rawPubKeys)) for i, rawPubKey := range rawPubKeys { if _, seen := seenKeys[rawPubKey]; seen { str := fmt.Sprintf("duplicated public key: %v", rawPubKey) return nil, newError(ErrKeyDuplicate, str, nil) } seenKeys[rawPubKey] = true key, err := hdkeychain.NewKeyFromString(rawPubKey) if err != nil { str := fmt.Sprintf("invalid extended public key %v", rawPubKey) return nil, newError(ErrKeyChain, str, err) } if key.IsPrivate() { str := fmt.Sprintf("private keys not accepted: %v", rawPubKey) return nil, newError(ErrKeyIsPrivate, str, nil) } keys[i] = key } return keys, nil }