taldir

Directory service to resolve wallet mailboxes by messenger addresses
Log | Files | Refs | Submodules | README | LICENSE

commit 02c38f462c811d1b598ba7e239e267ac7ac43538
parent f5099df82d8053e276df4f857230b27acb884f0b
Author: Martin Schanzenbach <schanzen@gnunet.org>
Date:   Tue, 12 Jul 2022 10:04:44 +0200

fixup durations and cost calculation

Diffstat:
Mcmd/taldir-server/main_test.go | 5++++-
Mpkg/rest/taldir.go | 37+++++++++++++++++++++++++++----------
Mpkg/util/helper.go | 4++--
3 files changed, 33 insertions(+), 13 deletions(-)

diff --git a/cmd/taldir-server/main_test.go b/cmd/taldir-server/main_test.go @@ -37,12 +37,13 @@ import ( var t taldir.Taldir +// Note: This duration will be rounded down to 20 Months (= 51840000000000) var validRegisterRequest = []byte(` { "address": "abc@test", "public_key": "000G006XE97PTWV3B7AJNCRQZA6BF26HPV3XZ07293FMY7KD4181946A90", "inbox_url": "myinbox@xyz", - "duration": 51840000000000 + "duration": 53135000000000 } `) @@ -310,6 +311,7 @@ func TestUnsupportedMethod(s *testing.T) { func TestPaymentRequiredMethod(s *testing.T) { t.ClearDatabase() + t.MonthlyFee = "KUDOS:5" httpmock.Activate() defer httpmock.DeactivateAndReset() req, _ := http.NewRequest("POST", "/register/test-cost", bytes.NewBuffer(validRegisterRequest)) @@ -317,6 +319,7 @@ func TestPaymentRequiredMethod(s *testing.T) { httpmock.RegisterResponder("GET", "http://merchant.taldir/instances/myInstance/private/orders/testOrder1234", httpmock.NewStringResponder(200, newOrderStatusUnpaidMockResponse)) response := executeRequest(req) + t.MonthlyFee = "KUDOS:0" if http.StatusPaymentRequired != response.Code { s.Errorf("Expected response code %d. Got %d\n", http.StatusPaymentRequired, response.Code) } diff --git a/pkg/rest/taldir.go b/pkg/rest/taldir.go @@ -91,6 +91,9 @@ type Taldir struct { // Merchant object Merchant taler.Merchant + + // Monthly fee amount + MonthlyFee string } type VersionResponse struct { @@ -260,6 +263,13 @@ type ValidationConfirmation struct { Solution string `json:"solution"` } +// NOTE: Go stores durations as nanoseconds. TalDir usually operates on microseconds +const MONTH_DURATION_US = 2592000000000 + +// 1 Month as Go duration +const MONTH_DURATION = time.Duration(MONTH_DURATION_US * 1000) + + // Primary lookup function. // Allows the caller to query a wallet key using the hash(!) of the // identity, e.g. SHA512(<email address>) @@ -338,7 +348,8 @@ func (t *Taldir) validationRequest(w http.ResponseWriter, r *http.Request){ } entry.HsAddress = saltHAddress(validation.HAddress, t.Salt) entry.Inbox = validation.Inbox - entry.Duration = time.Duration(entry.Duration.Microseconds() + validation.Duration) + tmpDuration := (entry.Duration.Microseconds() + validation.Duration) * 1000 + entry.Duration = time.Duration(tmpDuration) entry.RegisteredAt = time.Now().UnixMicro() entry.PublicKey = validation.PublicKey err = t.Db.First(&entry, "hs_address = ?", entry.HsAddress).Error @@ -383,7 +394,7 @@ func (t *Taldir) registerRequest(w http.ResponseWriter, r *http.Request){ errDetail.Hint = "Unsupported method" errDetail.Detail = "Given method: " + vars["method"] resp, _ := json.Marshal(errDetail) - w.WriteHeader(404) + w.WriteHeader(http.StatusNotFound) w.Write(resp) return } @@ -395,13 +406,16 @@ func (t *Taldir) registerRequest(w http.ResponseWriter, r *http.Request){ validation.HAddress = h_address hs_address := saltHAddress(validation.HAddress, t.Salt) err = t.Db.First(&entry, "hs_address = ?", hs_address).Error - validation.Duration = req.Duration + // Round to the nearest multiple of a month + reqDuration := time.Duration(req.Duration * 1000) + reqDuration = reqDuration.Round(MONTH_DURATION) + validation.Duration = reqDuration.Microseconds() if err == nil { log.Println("Entry for this address already exists..") regAt := time.UnixMicro(entry.RegisteredAt) entryValidity := regAt.Add(entry.Duration) - requestedValidity := time.Now().Add(time.Duration(req.Duration)) - log.Printf("Entry valid until: %s , requested until: %s\n", entryValidity, time.Now().Add(time.Duration(req.Duration))) + requestedValidity := time.Now().Add(reqDuration) + log.Printf("Entry valid until: %s , requested until: %s\n", entryValidity, time.Now().Add(reqDuration)) if requestedValidity.Before(entryValidity) { w.WriteHeader(http.StatusOK) w.Header().Set("Content-Type", "application/json") @@ -449,16 +463,18 @@ func (t *Taldir) registerRequest(w http.ResponseWriter, r *http.Request){ return } - cost, currency, err := util.CalculateCost(t.Cfg.Section("taldir-" + vars["method"]).Key("challenge_fee").MustString("KUDOS:0"), - t.Cfg.Section("taldir").Key("monthly_fee").MustString("KUDOS:0"), - time.Duration(validation.Duration), - time.Duration(2592000000000)) //Fixme 1 Month in us + fixedCost := t.Cfg.Section("taldir-" + vars["method"]).Key("challenge_fee").MustString("KUDOS:0") + sliceDuration := time.Duration(validation.Duration * 1000) + cost, currency, err := util.CalculateCost(t.MonthlyFee, + fixedCost, + sliceDuration, + MONTH_DURATION) //Fixme 1 Month in us if err != nil { w.WriteHeader(http.StatusInternalServerError) return } - log.Printf("The calculated cost for this registration is: %s:%f", currency, cost) + log.Printf("The calculated cost for this registration is: %s:%f for a delta duration of %f", currency, cost, float64(validation.Duration) / float64(MONTH_DURATION.Microseconds())) if cost > 0 { // FIXME what if provided order ID and validation order ID differ??? if len(order.Id) == 0 { @@ -740,6 +756,7 @@ func (t *Taldir) Initialize(cfgfile string) { if err != nil { log.Fatal(err) } + t.MonthlyFee = t.Cfg.Section("taldir").Key("monthly_fee").MustString("KUDOS:0") psqlconn := fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=%s sslmode=disable", t.Cfg.Section("taldir-pq").Key("host").MustString("localhost"), diff --git a/pkg/util/helper.go b/pkg/util/helper.go @@ -94,7 +94,7 @@ func ParseAmount(amount string) (float64, string, error) { // Check if this is a non-zero, positive amount func CalculateCost(sliceCostAmount string, fixedCostAmount string, howLong time.Duration, sliceDuration time.Duration) (float64, string, error) { - sliceCount := howLong.Microseconds() / sliceDuration.Microseconds() + sliceCount := float64(howLong.Microseconds()) / float64(sliceDuration.Microseconds()) sliceCost, curA, err := ParseAmount(sliceCostAmount) if nil != err { return 0.0, "", errors.New("Currency in amount malformed") @@ -106,5 +106,5 @@ func CalculateCost(sliceCostAmount string, fixedCostAmount string, howLong time. if curA != curB { return 0.0, "", errors.New("Currency in amounts different") } - return (float64(sliceCount) * sliceCost) + fixedCost, curA, nil + return (sliceCount * sliceCost) + fixedCost, curA, nil }