diff --git a/loopd/swapclient_server.go b/loopd/swapclient_server.go index d463f80..08bcb20 100644 --- a/loopd/swapclient_server.go +++ b/loopd/swapclient_server.go @@ -156,21 +156,22 @@ func (s *swapClientServer) LoopOut(ctx context.Context, return nil, err } + // Infer if the publication deadline is set in milliseconds. + publicationDeadline := getPublicationDeadline(in.SwapPublicationDeadline) + req := &loop.OutRequest{ - Amount: btcutil.Amount(in.Amt), - DestAddr: sweepAddr, - MaxMinerFee: btcutil.Amount(in.MaxMinerFee), - MaxPrepayAmount: btcutil.Amount(in.MaxPrepayAmt), - MaxPrepayRoutingFee: btcutil.Amount(in.MaxPrepayRoutingFee), - MaxSwapRoutingFee: btcutil.Amount(in.MaxSwapRoutingFee), - MaxSwapFee: btcutil.Amount(in.MaxSwapFee), - SweepConfTarget: sweepConfTarget, - HtlcConfirmations: in.HtlcConfirmations, - SwapPublicationDeadline: time.Unix( - int64(in.SwapPublicationDeadline), 0, - ), - Label: in.Label, - Initiator: in.Initiator, + Amount: btcutil.Amount(in.Amt), + DestAddr: sweepAddr, + MaxMinerFee: btcutil.Amount(in.MaxMinerFee), + MaxPrepayAmount: btcutil.Amount(in.MaxPrepayAmt), + MaxPrepayRoutingFee: btcutil.Amount(in.MaxPrepayRoutingFee), + MaxSwapRoutingFee: btcutil.Amount(in.MaxSwapRoutingFee), + MaxSwapFee: btcutil.Amount(in.MaxSwapFee), + SweepConfTarget: sweepConfTarget, + HtlcConfirmations: in.HtlcConfirmations, + SwapPublicationDeadline: publicationDeadline, + Label: in.Label, + Initiator: in.Initiator, } switch { @@ -538,13 +539,14 @@ func (s *swapClientServer) LoopOutQuote(ctx context.Context, if err != nil { return nil, err } + + publicactionDeadline := getPublicationDeadline(req.SwapPublicationDeadline) + quote, err := s.impl.LoopOutQuote(ctx, &loop.LoopOutQuoteRequest{ - Amount: btcutil.Amount(req.Amt), - SweepConfTarget: confTarget, - SwapPublicationDeadline: time.Unix( - int64(req.SwapPublicationDeadline), 0, - ), - Initiator: defaultLoopdInitiator, + Amount: btcutil.Amount(req.Amt), + SweepConfTarget: confTarget, + SwapPublicationDeadline: publicactionDeadline, + Initiator: defaultLoopdInitiator, }) if err != nil { return nil, err @@ -1249,3 +1251,19 @@ func hasBandwidth(channels []lndclient.ChannelInfo, amt btcutil.Amount, return false, 0 } + +// getPublicationDeadline returns the publication deadline for a swap given the +// unix timestamp. If the timestamp is believed to be in milliseconds, then it +// is converted to seconds. +func getPublicationDeadline(unixTimestamp uint64) time.Time { + length := len(fmt.Sprintf("%d", unixTimestamp)) + if length >= 13 { + // Likely a millisecond timestamp + secs := unixTimestamp / 1000 + nsecs := (unixTimestamp % 1000) * 1e6 + return time.Unix(int64(secs), int64(nsecs)) + } else { + // Likely a second timestamp + return time.Unix(int64(unixTimestamp), 0) + } +} diff --git a/loopdb/sql_test.go b/loopdb/sql_test.go index 1ac3410..402de8b 100644 --- a/loopdb/sql_test.go +++ b/loopdb/sql_test.go @@ -346,13 +346,11 @@ func TestIssue615(t *testing.T) { Index: 2, }, }, - MaxMinerFee: 10, - MaxSwapFee: 20, - + MaxMinerFee: 10, + MaxSwapFee: 20, InitiationHeight: 99, - - InitiationTime: time.Now(), - ProtocolVersion: ProtocolVersionMuSig2, + InitiationTime: time.Now(), + ProtocolVersion: ProtocolVersionMuSig2, }, MaxPrepayRoutingFee: 40, PrepayInvoice: "prepayinvoice", diff --git a/loopdb/sqlite.go b/loopdb/sqlite.go index 9add23b..a264822 100644 --- a/loopdb/sqlite.go +++ b/loopdb/sqlite.go @@ -316,6 +316,11 @@ func (r *SqliteTxOptions) ReadOnly() bool { func parseSqliteTimeStamp(dateTimeStr string) (time.Time, error) { // Split the date and time parts. parts := strings.Fields(strings.TrimSpace(dateTimeStr)) + if len(parts) <= 2 { + return time.Time{}, fmt.Errorf("invalid timestamp format: %v", + dateTimeStr) + } + datePart, timePart := parts[0], parts[1] return parseTimeParts(datePart, timePart) @@ -328,6 +333,11 @@ func parseSqliteTimeStamp(dateTimeStr string) (time.Time, error) { func parsePostgresTimeStamp(dateTimeStr string) (time.Time, error) { // Split the date and time parts. parts := strings.Split(dateTimeStr, "T") + if len(parts) != 2 { + return time.Time{}, fmt.Errorf("invalid timestamp format: %v", + dateTimeStr) + } + datePart, timePart := parts[0], strings.TrimSuffix(parts[1], "Z") return parseTimeParts(datePart, timePart) @@ -338,6 +348,10 @@ func parsePostgresTimeStamp(dateTimeStr string) (time.Time, error) { func parseTimeParts(datePart, timePart string) (time.Time, error) { // Parse the date. dateParts := strings.Split(datePart, "-") + if len(dateParts) != 3 { + return time.Time{}, fmt.Errorf("invalid date format: %v", + datePart) + } year, err := strconv.Atoi(dateParts[0]) if err != nil { @@ -356,6 +370,10 @@ func parseTimeParts(datePart, timePart string) (time.Time, error) { // Parse the time. timeParts := strings.Split(timePart, ":") + if len(timeParts) != 3 { + return time.Time{}, fmt.Errorf("invalid time format: %v", + timePart) + } hour, err := strconv.Atoi(timeParts[0]) if err != nil {