cashless2ecash

cashless2ecash: pay with cards for digital cash (experimental)
Log | Files | Refs | README

commit 52ba853cc491b2333845bcdc79f491c85ca2eb0e
parent abd2a391f8169e5b387351333b659b9dfb411b64
Author: Joel-Haeberli <haebu@rubigen.ch>
Date:   Mon,  8 Apr 2024 19:09:32 +0200

fix: serialization and logging

Diffstat:
Mc2ec/auth.go | 8++++----
Mc2ec/bank-integration.go | 10+++++-----
Mc2ec/http-util.go | 8+++++---
Mc2ec/logger.go | 25+++++++++++++------------
Mc2ec/main.go | 2+-
Mc2ec/model.go | 6+++---
Mc2ec/postgres.go | 50++++++++++++++++++++++++++------------------------
Mc2ec/wallee-attestor.go | 2+-
Mc2ec/wallee-client.go | 4++--
Asimulation/README | 0
Msimulation/c2ec-simulation | 0
Msimulation/sim-wallet.go | 12+++++++-----
12 files changed, 67 insertions(+), 60 deletions(-)

diff --git a/c2ec/auth.go b/c2ec/auth.go @@ -57,7 +57,7 @@ func AuthenticateTerminal(req *http.Request) bool { if err != nil { return false } - LogInfo(fmt.Sprintf("req=%s by terminal with id=%d, provider=%s", req.RequestURI, terminalId, provider)) + LogInfo("auth", fmt.Sprintf("req=%s by terminal with id=%d, provider=%s", req.RequestURI, terminalId, provider)) terminal, err := DB.GetTerminalById(terminalId) if err != nil { @@ -65,18 +65,18 @@ func AuthenticateTerminal(req *http.Request) bool { } if !terminal.Active { - LogWarn(fmt.Sprintf("request from inactive terminal. id=%d", terminalId)) + LogWarn("auth", fmt.Sprintf("request from inactive terminal. id=%d", terminalId)) return false } prvdr, err := DB.GetTerminalProviderByName(provider) if err != nil { - LogWarn(fmt.Sprintf("failed requesting provider by name %s", err.Error())) + LogWarn("auth", fmt.Sprintf("failed requesting provider by name %s", err.Error())) return false } if terminal.ProviderId != prvdr.ProviderId { - LogWarn("terminal's provider id did not match provider id of supplied provider") + LogWarn("auth", "terminal's provider id did not match provider id of supplied provider") return false } diff --git a/c2ec/bank-integration.go b/c2ec/bank-integration.go @@ -69,7 +69,7 @@ func bankIntegrationConfig(res http.ResponseWriter, req *http.Request) { serializedCfg, err := NewJsonCodec[BankIntegrationConfig]().EncodeToBytes(&cfg) if err != nil { - LogInfo(fmt.Sprintf("failed serializing config: %s", err.Error())) + LogInfo("bank-integration-api", fmt.Sprintf("failed serializing config: %s", err.Error())) res.WriteHeader(HTTP_INTERNAL_SERVER_ERROR) return } @@ -83,7 +83,7 @@ func handleWithdrawalRegistration(res http.ResponseWriter, req *http.Request) { jsonCodec := NewJsonCodec[C2ECWithdrawRegistration]() registration, err := ReadStructFromBody(req, jsonCodec) if err != nil { - + LogWarn("bank-integration-api", fmt.Sprintf("invalid body for withdrawal registration error=%s", err.Error())) err := WriteProblem(res, HTTP_BAD_REQUEST, &RFC9457Problem{ TypeUri: TALER_URI_PROBLEM_PREFIX + "/C2EC_WITHDRAW_REGISTRATION_INVALID_REQ", Title: "invalid request", @@ -99,7 +99,7 @@ func handleWithdrawalRegistration(res http.ResponseWriter, req *http.Request) { // read and validate the wopid path parameter wopid := req.PathValue(WOPID_PARAMETER) if !WopidValid(wopid) { - LogWarn("wopid " + wopid + " not valid") + LogWarn("bank-integration-api", "wopid "+wopid+" not valid") if wopid == "" { err := WriteProblem(res, HTTP_BAD_REQUEST, &RFC9457Problem{ TypeUri: TALER_URI_PROBLEM_PREFIX + "/C2EC_INVALID_PATH_PARAMETER", @@ -167,7 +167,7 @@ func handleWithdrawalStatus(res http.ResponseWriter, req *http.Request) { // read and validate the wopid path parameter wopid := req.PathValue(WOPID_PARAMETER) if !WopidValid(wopid) { - LogWarn("wopid " + wopid + " not valid") + LogWarn("bank-integration-api", "wopid "+wopid+" not valid") if wopid == "" { err := WriteProblem(res, HTTP_BAD_REQUEST, &RFC9457Problem{ TypeUri: TALER_URI_PROBLEM_PREFIX + "/C2EC_INVALID_PATH_PARAMETER", @@ -233,7 +233,7 @@ func handlePaymentNotification(res http.ResponseWriter, req *http.Request) { wopid := req.PathValue(WOPID_PARAMETER) if !WopidValid(wopid) { - LogWarn("wopid " + wopid + " not valid") + LogWarn("bank-integration-api", "wopid "+wopid+" not valid") if wopid == "" { err := WriteProblem(res, HTTP_BAD_REQUEST, &RFC9457Problem{ TypeUri: TALER_URI_PROBLEM_PREFIX + "/C2EC_INVALID_PATH_PARAMETER", diff --git a/c2ec/http-util.go b/c2ec/http-util.go @@ -4,6 +4,7 @@ import ( "bytes" "errors" "fmt" + "io" "net/http" "strings" ) @@ -147,14 +148,15 @@ func ReadStructFromBody[T any](req *http.Request, codec Codec[T]) (*T, error) { func ReadBody(req *http.Request) ([]byte, error) { if req.ContentLength < 0 { - return make([]byte, 0), nil + return nil, errors.New("malformed body") } - body := make([]byte, req.ContentLength) - _, err := req.Body.Read(body) + body, err := io.ReadAll(req.Body) if err != nil { + LogError("http-util", err) return nil, err } + LogInfo("http-util", "read body from request. body="+string(body)) return body, nil } diff --git a/c2ec/logger.go b/c2ec/logger.go @@ -8,8 +8,8 @@ import ( const LOG_PATH = "c2ec-log.txt" -// LEVEL | TIME | MESSAGE -const LOG_PATTERN = "%d | %s | %s" +// LEVEL | TIME | SRC | MESSAGE +const LOG_PATTERN = "level=%d | time=%s | src=%s | %s" const TIME_FORMAT = "yyyy-MM-dd hh:mm:ss" type LogLevel int @@ -20,29 +20,29 @@ const ( ERROR ) -func LogError(err error) { +func LogError(src string, err error) { - go logAppendError(ERROR, err) + go logAppendError(src, ERROR, err) } -func LogWarn(msg string) { +func LogWarn(src string, msg string) { - go logAppend(WARN, msg) + go logAppend(src, WARN, msg) } -func LogInfo(msg string) { +func LogInfo(src string, msg string) { - go logAppend(INFO, msg) + go logAppend(src, INFO, msg) } -func logAppendError(level LogLevel, err error) { +func logAppendError(src string, level LogLevel, err error) { - logAppend(level, err.Error()) + logAppend(src, level, err.Error()) } -func logAppend(level LogLevel, msg string) { +func logAppend(src string, level LogLevel, msg string) { - openAppendClose(fmt.Sprintf(LOG_PATTERN, level, time.Now().Format(time.UnixDate), msg)) + openAppendClose(fmt.Sprintf(LOG_PATTERN, level, time.Now().Format(time.UnixDate), src, msg)) } func openAppendClose(s string) { @@ -53,6 +53,7 @@ func openAppendClose(s string) { // if file does not yet exist, open with create flag. f, err = os.OpenFile(LOG_PATH, os.O_CREATE|os.O_APPEND|os.O_WRONLY, os.ModeAppend) if err != nil || f == nil { + fmt.Println("error: ", err.Error()) panic("failed opening or creating log file") } } diff --git a/c2ec/main.go b/c2ec/main.go @@ -42,7 +42,7 @@ var PROVIDER_CLIENTS = map[string]ProviderClient{} // 6. listen for incoming requests (as specified in config) func main() { - LogInfo(fmt.Sprintf("starting c2ec at %s", time.Now().Format(time.UnixDate))) + LogInfo("main", fmt.Sprintf("starting c2ec at %s", time.Now().Format(time.UnixDate))) cfgPath := DEFAULT_C2EC_CONFIG_PATH if len(os.Args) > 1 && os.Args[1] != "" { diff --git a/c2ec/model.go b/c2ec/model.go @@ -53,11 +53,11 @@ func ToWithdrawalOpStatus(s string) (WithdrawalOperationStatus, error) { func WopidValid(wopid string) bool { decoded, err := base64.URLEncoding.DecodeString(wopid) - LogInfo(fmt.Sprintf("decoded wopid=%s", string(decoded))) if err != nil { - LogError(err) + LogError("model", err) + return false } - return err != nil //&& len(wopidBytes) == 32 + return len(decoded) == 32 } type ErrorDetail struct { diff --git a/c2ec/postgres.go b/c2ec/postgres.go @@ -127,7 +127,7 @@ func (db *C2ECPostgres) RegisterWithdrawal( terminalId, ) if err != nil { - LogError(err) + LogError("postgres", err) return err } res.Close() @@ -141,7 +141,7 @@ func (db *C2ECPostgres) GetWithdrawalByWopid(wopid string) (*Withdrawal, error) PS_GET_WITHDRAWAL_BY_WOPID, wopid, ); err != nil { - LogError(err) + LogError("postgres", err) if row != nil { row.Close() } @@ -152,7 +152,7 @@ func (db *C2ECPostgres) GetWithdrawalByWopid(wopid string) (*Withdrawal, error) withdrawals, err := pgx.CollectRows(row, pgx.RowToAddrOfStructByName[Withdrawal]) if err != nil { - LogError(err) + LogError("postgres", err) return nil, err } @@ -169,7 +169,7 @@ func (db *C2ECPostgres) GetWithdrawalByProviderTransactionId(tid string) (*Withd PS_GET_WITHDRAWAL_BY_PTID, tid, ); err != nil { - LogError(err) + LogError("postgres", err) if row != nil { row.Close() } @@ -180,7 +180,7 @@ func (db *C2ECPostgres) GetWithdrawalByProviderTransactionId(tid string) (*Withd withdrawals, err := pgx.CollectRows(row, pgx.RowToAddrOfStructByName[Withdrawal]) if err != nil { - LogError(err) + LogError("postgres", err) return nil, err } @@ -206,7 +206,7 @@ func (db *C2ECPostgres) NotifyPayment( fees, ) if err != nil { - LogError(err) + LogError("postgres", err) return err } res.Close() @@ -219,7 +219,7 @@ func (db *C2ECPostgres) GetAttestableWithdrawals() ([]*Withdrawal, error) { db.ctx, PS_GET_UNCONFIRMED_WITHDRAWALS, ); err != nil { - LogError(err) + LogError("postgres", err) if row != nil { row.Close() } @@ -230,7 +230,7 @@ func (db *C2ECPostgres) GetAttestableWithdrawals() ([]*Withdrawal, error) { withdrawals, err := pgx.CollectRows(row, pgx.RowToAddrOfStructByName[Withdrawal]) if err != nil { - LogError(err) + LogError("postgres", err) return nil, err } @@ -256,7 +256,7 @@ func (db *C2ECPostgres) FinaliseWithdrawal( withdrawalId, ) if err != nil { - LogError(err) + LogError("postgres", err) return err } res.Close() @@ -305,7 +305,7 @@ func (db *C2ECPostgres) GetConfirmedWithdrawals(start int, delta int) ([]*Withdr } if err != nil { - LogError(err) + LogError("postgres", err) if row != nil { row.Close() } @@ -316,7 +316,7 @@ func (db *C2ECPostgres) GetConfirmedWithdrawals(start int, delta int) ([]*Withdr withdrawals, err := pgx.CollectRows(row, pgx.RowToAddrOfStructByName[Withdrawal]) if err != nil { - LogError(err) + LogError("postgres", err) return nil, err } @@ -331,7 +331,7 @@ func (db *C2ECPostgres) GetTerminalProviderByName(name string) (*Provider, error PS_GET_PROVIDER_BY_NAME, name, ); err != nil { - LogError(err) + LogError("postgres", err) if row != nil { row.Close() } @@ -342,7 +342,7 @@ func (db *C2ECPostgres) GetTerminalProviderByName(name string) (*Provider, error provider, err := pgx.CollectRows(row, pgx.RowToAddrOfStructByName[Provider]) if err != nil { - LogError(err) + LogError("postgres", err) return nil, err } @@ -361,7 +361,7 @@ func (db *C2ECPostgres) GetTerminalProviderByPaytoTargetType(paytoTargetType str PS_GET_PROVIDER_BY_PAYTO_TARGET_TYPE, paytoTargetType, ); err != nil { - LogError(err) + LogError("postgres", err) if row != nil { row.Close() } @@ -372,7 +372,7 @@ func (db *C2ECPostgres) GetTerminalProviderByPaytoTargetType(paytoTargetType str provider, err := pgx.CollectRows(row, pgx.RowToAddrOfStructByName[Provider]) if err != nil { - LogError(err) + LogError("postgres", err) return nil, err } @@ -391,7 +391,7 @@ func (db *C2ECPostgres) GetTerminalById(id int) (*Terminal, error) { PS_GET_TERMINAL_BY_ID, id, ); err != nil { - LogError(err) + LogError("postgres", err) if row != nil { row.Close() } @@ -402,7 +402,7 @@ func (db *C2ECPostgres) GetTerminalById(id int) (*Terminal, error) { terminals, err := pgx.CollectRows(row, pgx.RowToAddrOfStructByName[Terminal]) if err != nil { - LogError(err) + LogError("postgres", err) return nil, err } @@ -421,7 +421,7 @@ func (db *C2ECPostgres) GetTransferById(requestUid HashCode) (*Transfer, error) PS_GET_TRANSFER_BY_ID, requestUid, ); err != nil { - LogError(err) + LogError("postgres", err) if row != nil { row.Close() } @@ -432,7 +432,7 @@ func (db *C2ECPostgres) GetTransferById(requestUid HashCode) (*Transfer, error) transfers, err := pgx.CollectRows(row, pgx.RowToAddrOfStructByName[Transfer]) if err != nil { - LogError(err) + LogError("postgres", err) return nil, err } @@ -453,7 +453,7 @@ func (db *C2ECPostgres) AddTransfer(requestId HashCode, requestHash string) erro requestHash, ) if err != nil { - LogError(err) + LogError("postgres", err) return err } res.Close() @@ -472,7 +472,9 @@ func (db *C2ECPostgres) ListenForWithdrawalStatusChange( listener := newChannelListener(db.pool.Config().ConnConfig, channel, pgNotification) go func() { + LogInfo("postgres", fmt.Sprintf("listening for %s", wopid)) if err := listener.Listen(ctx); err != nil { + LogError("postgres", err) errs <- err } // close the channel we send results, because listener has finished. @@ -481,19 +483,19 @@ func (db *C2ECPostgres) ListenForWithdrawalStatusChange( select { case e := <-errs: - LogError(e) + LogError("postgres", e) return "", e case <-ctx.Done(): err := ctx.Err() msg := "context sent done signal while listening for status change" if err != nil { - LogError(err) + LogError("postgres", err) } else { - LogWarn(msg) + LogWarn("postgres", msg) } return "", errors.New(msg) case n := <-pgNotification: - LogInfo(fmt.Sprintf("received notification for channel %s: %s", n.Channel, n.Payload)) + LogInfo("postgres", fmt.Sprintf("received notification for channel %s: %s", n.Channel, n.Payload)) return WithdrawalOperationStatus(n.Payload), nil } } diff --git a/c2ec/wallee-attestor.go b/c2ec/wallee-attestor.go @@ -54,7 +54,7 @@ func (wa *WalleeAttestor) Listen( go func() { err := wa.listener.Listen(ctx) if err != nil { - LogError(err) + LogError("wallee-attestor", err) errs <- err } close(notificationChannel) diff --git a/c2ec/wallee-client.go b/c2ec/wallee-client.go @@ -174,7 +174,7 @@ func calculateWalleeAuthToken( key := make([]byte, base64.StdEncoding.DecodedLen(len(userKeyBase64))) _, err := base64.StdEncoding.Decode(key, []byte(userKeyBase64)) if err != nil { - LogError(err) + LogError("wallee-client", err) return "", err } @@ -185,7 +185,7 @@ func calculateWalleeAuthToken( macer := hmac.New(sha512.New, key) _, err = macer.Write(authMsg) if err != nil { - LogError(err) + LogError("wallee-client", err) return "", err } mac := make([]byte, 64) diff --git a/simulation/README b/simulation/README diff --git a/simulation/c2ec-simulation b/simulation/c2ec-simulation Binary files differ. diff --git a/simulation/sim-wallet.go b/simulation/sim-wallet.go @@ -45,17 +45,19 @@ func Wallet(in chan *SimulatedPhysicalInteraction, out chan *SimulatedPhysicalIn } cdc := NewJsonCodec[C2ECWithdrawRegistration]() - body, err := cdc.EncodeToBytes(&C2ECWithdrawRegistration{ - ReservePubKey: EddsaPublicKey(simulateReservePublicKey()), - TerminalId: uint64(tid), - }) + reg := new(C2ECWithdrawRegistration) + reg.ReservePubKey = EddsaPublicKey(simulateReservePublicKey()) + reg.TerminalId = uint64(tid) + body, err := cdc.EncodeToBytes(reg) + regByte := bytes.NewBuffer(body) + // fmt.Println("body (bytes):", regByte.Bytes()) if err != nil { kill <- err } res, err := http.Post( registrationUrl, cdc.HttpApplicationContentHeader(), - bytes.NewBuffer(body), + bytes.NewReader(regByte.Bytes()), ) if res.StatusCode != 204 {