func (ce *CtrlEngine) upkeepAccounts( unmappedID, period, remaining string, statfp io.Writer, ) error { mappedID, err := identity.Map(unmappedID) if err != nil { return err } exec, now, err := checkExecution(mappedID, period, func(mappedID string) (int64, error) { return ce.msgDB.GetUpkeepAccounts(mappedID) }) if err != nil { return err } if !exec { log.Info(statfp, "ctrlengine: upkeep accounts not due") fmt.Fprintf(statfp, "ctrlengine: upkeep accounts not due\n") return nil } remain, err := time.ParseDuration(remaining) if err != nil { return err } contacts, err := ce.msgDB.GetAccounts(mappedID) if err != nil { return err } for _, contact := range contacts { privkey, server, _, _, _, _, err := ce.msgDB.GetAccount(mappedID, contact) if err != nil { return err } last, err := ce.msgDB.GetAccountTime(mappedID, contact) if err != nil { return err } if last == 0 { last, err = mixclient.AccountStat(privkey, server, def.CACert) if err != nil { return err } err := ce.msgDB.SetAccountTime(mappedID, contact, last) if err != nil { return err } } if times.Now()+int64(remain.Seconds()) >= last { token, err := wallet.GetToken(ce.client, def.AccdUsage, def.AccdOwner) if err != nil { return err } _, err = mixclient.PayAccount(privkey, token.Token, server, def.CACert) if err != nil { ce.client.UnlockToken(token.Hash) return log.Error(err) } ce.client.DelToken(token.Hash) last, err = mixclient.AccountStat(privkey, server, def.CACert) if err != nil { return err } err = ce.msgDB.SetAccountTime(mappedID, contact, last) if err != nil { return err } } } // record time of execution if err := ce.msgDB.SetUpkeepAccounts(mappedID, now); err != nil { return err } return nil }
func (ce *CtrlEngine) uidNew( c *cli.Context, minDelay, maxDelay int32, host string, ) error { // make sure the ID is well-formed unmapped := c.String("id") id, domain, err := identity.MapPlus(unmapped) if err != nil { return err } // sync corresponding hashchain if id != "keyserver" { if err := ce.upkeepHashchain(c, domain, c.String("host")); err != nil { return err } } // check that ID has not been registered already by the same user unmappedID, _, err := ce.msgDB.GetNym(id) if err != nil { return err } if unmappedID != "" { return log.Error(ErrUserIDOwned) } // check that ID has not been registered already by other user err = mutecryptHashchainSearch(c, id, c.String("host"), ce.passphrase) if err == nil { return log.Error(ErrUserIDTaken) } // get token from wallet token, err := wallet.GetToken(ce.client, def.AccdUsage, def.AccdOwner) if err != nil { return err } // register account for UID _, privkey, err := ed25519.GenerateKey(cipher.RandReader) if err != nil { return log.Error(err) } server, err := mixclient.PayAccount(privkey, token.Token, "", def.CACert) if err != nil { ce.client.UnlockToken(token.Hash) return log.Error(err) } ce.client.DelToken(token.Hash) // generate secret for account var secret [64]byte if _, err := io.ReadFull(cipher.RandReader, secret[:]); err != nil { return err } // get mixaddress and nymaddress for KeyInit message expire := times.ThirtyDaysLater() // TODO: make this settable singleUse := false // TODO correct? var pubkey [ed25519.PublicKeySize]byte copy(pubkey[:], privkey[32:]) mixaddress, nymaddress, err := util.NewNymAddress(domain, secret[:], expire, singleUse, minDelay, maxDelay, id, &pubkey, server, def.CACert) if err != nil { return err } // generate UID err = mutecryptNewUID(c, ce.passphrase, id, domain, host, mixaddress, nymaddress, ce.client) if err != nil { return err } // save name mapping if err := ce.msgDB.AddNym(id, unmapped, c.String("full-name")); err != nil { return err } // register account for UID err = ce.msgDB.AddAccount(id, "", privkey, server, &secret, minDelay, maxDelay) if err != nil { return err } // set active UID, if this was the first UID active, err := ce.msgDB.GetValue(msgdb.ActiveUID) if err != nil { return err } if active == "" { if err := ce.msgDB.AddValue(msgdb.ActiveUID, unmapped); err != nil { return err } } return nil }