// newBroadcastsStore creates a new BroadcastAddresses object after doing the // necessary initialization. func newBroadcastsStore(db *bolt.DB, username string) (*BroadcastAddresses, error) { b := &BroadcastAddresses{ db: db, username: []byte(username), addrs: make([]bmutil.Address, 0), } err := db.Update(func(tx *bolt.Tx) error { userbucket, err := tx.CreateBucketIfNotExists([]byte(username)) if err != nil { return err } bucket, err := userbucket.CreateBucketIfNotExists(broadcastAddressesBucket) if err != nil { return err } return bucket.ForEach(func(k, _ []byte) error { addr, err := bmutil.DecodeAddress(string(k)) if err != nil { return err } b.addrs = append(b.addrs, *addr) return nil }) }) if err != nil { return nil, err } return b, nil }
// Remove removes an address from the store. func (b *BroadcastAddresses) Remove(address string) error { addr, err := bmutil.DecodeAddress(address) if err != nil { return err } k := []byte(address) err = b.db.Update(func(tx *bolt.Tx) error { if tx.Bucket(b.username).Bucket(broadcastAddressesBucket).Get(k) == nil { return ErrNotFound } return tx.Bucket(broadcastAddressesBucket).Delete(k) }) if err != nil { return err } for i, t := range b.addrs { if bytes.Equal(t.Ripe[:], addr.Ripe[:]) { // Delete. b.addrs = append(b.addrs[:i], b.addrs[i+1:]...) return nil } } return nil }
// GetIdentity returns the public identity corresponding to the given address // if it exists. func (c *Client) GetIdentity(address string) (*identity.Public, error) { addr, err := bmutil.DecodeAddress(address) if err != nil { return nil, fmt.Errorf("Address decode failed: %v", addr) } res, err := c.bmd.GetIdentity(context.Background(), &pb.GetIdentityRequest{ Address: address, }) if grpc.Code(err) == codes.NotFound { return nil, ErrIdentityNotFound } else if err != nil { return nil, err } signKey, err := btcec.ParsePubKey(res.SigningKey, btcec.S256()) if err != nil { return nil, err } encKey, err := btcec.ParsePubKey(res.EncryptionKey, btcec.S256()) if err != nil { return nil, err } return identity.NewPublic(signKey, encKey, &pow.Data{ res.NonceTrials, res.ExtraBytes, }, addr.Version, addr.Stream), nil }
// emailToBM extracts a Bitmessage address from an e-mail address. func emailToBM(emailAddr string) (string, error) { addr, err := mail.ParseAddress(emailAddr) if err != nil { return "", err } if !emailRegex.Match([]byte(addr.Address)) { return "", ErrInvalidEmail } bm := strings.Split(addr.Address, "@")[0] if _, err := bmutil.DecodeAddress(bm); err != nil { return "", ErrInvalidEmail } return bm, nil }
// Add adds a new address to the store. func (b *BroadcastAddresses) Add(address string) error { addr, err := bmutil.DecodeAddress(address) if err != nil { return err } k := []byte(address) v := []byte{} err = b.db.Update(func(tx *bolt.Tx) error { return tx.Bucket(b.username).Bucket(broadcastAddressesBucket).Put(k, v) }) if err != nil { return err } b.addrs = append(b.addrs, *addr) return nil }
// getOrRequestPublicIdentity retrieves the needed public identity from bmd // or sends a getpubkey request if it doesn't exist in its database. If both // return types are nil, it means a getpubkey request has been queued. func (s *server) getOrRequestPublicIdentity(user uint32, address string) (*identity.Public, error) { serverLog.Debug("getOrRequestPublicIdentity called for ", address) id, err := s.bmd.GetIdentity(address) if err == nil { return id, nil } else if err != rpc.ErrIdentityNotFound { return nil, err } addr, err := bmutil.DecodeAddress(address) if err != nil { return nil, fmt.Errorf("Failed to decode address: %v", err) } serverLog.Debug("getOrRequestPublicIdentity: address not found, send pubkey request.") // We don't have the identity so craft a getpubkey request. var tag wire.ShaHash copy(tag[:], addr.Tag()) msg := obj.NewGetPubKey(0, time.Now().Add(defaultGetpubkeyExpiry), addr.Version, addr.Stream, (*wire.RipeHash)(&addr.Ripe), &tag) // Enqueue the request for proof-of-work. b := wire.EncodeMessage(msg.MsgObject())[8:] // exclude nonce target := pow.CalculateTarget(uint64(len(b)), uint64(msg.Header().Expiration().Sub(time.Now()).Seconds()), pow.DefaultData) s.pow.Run(target, b, func(nonce pow.Nonce) { err := s.Send(append(nonce.Bytes(), b...)) if err != nil { serverLog.Error("Could not run pow: ", err) } // Store a record of the public key request. count, _ := s.pk.New(address) serverLog.Tracef("getOrRequestPublicIdentity: Requested address %s %d time(s).", address, count) }) return nil, nil }
// UnmarshalJSON unmarshals the object from JSON. Part of json.Unmarshaller // interface. func (id *PrivateID) UnmarshalJSON(in []byte) error { stored := &privateIDStore{} err := json.Unmarshal(in, stored) if err != nil { return err } if len(stored.Address) < 4 { return errors.New("address too short") } addr, err := bmutil.DecodeAddress(stored.Address) if err != nil { return err } signKey, err := bmutil.DecodeWIF(stored.SigningKey) if err != nil { return err } encKey, err := bmutil.DecodeWIF(stored.EncryptionKey) if err != nil { return err } id.Private.Address = *addr id.SigningKey = signKey id.EncryptionKey = encKey id.NonceTrialsPerByte = stored.NonceTrialsPerByte id.ExtraBytes = stored.ExtraBytes id.IsChan = stored.IsChan id.Disabled = stored.Disabled id.Imported = stored.Imported id.Name = stored.Name return nil }