diff --git a/wallet/res/values/strings-extra.xml b/wallet/res/values/strings-extra.xml
index 293c52a8e4..0c5db8aaa3 100644
--- a/wallet/res/values/strings-extra.xml
+++ b/wallet/res/values/strings-extra.xml
@@ -697,4 +697,6 @@
Not used
Revoked
Private / Public Keys (base64)
+ ahead
+ behind
\ No newline at end of file
diff --git a/wallet/res/values/strings.xml b/wallet/res/values/strings.xml
index 498deeaff5..cfd019d887 100644
--- a/wallet/res/values/strings.xml
+++ b/wallet/res/values/strings.xml
@@ -43,7 +43,7 @@
Manage apps
Check date & time settings
Your device time is off by %d minutes. You probably cannot send or receive Dash due to this problem.\n\nYou should check and if necessary correct your date, time and timezone settings.
- Your device time is off by %d seconds. You cannot use CoinJoin due to this problem.\n\nThe time settings on your device needs to be changed to “Set time automatically” to use CoinJoin.
+ Your device time is %s by %d seconds. You cannot use CoinJoin due to this problem.\n\nThe time settings on your device needs to be changed to “Set time automatically” to use CoinJoin.
Your device time is off by more than 2 seconds. You cannot use CoinJoin due to this problem.\n\nThe time settings on your device needs to be changed to “Set time automatically” before using CoinJoin.
Send Dash
Fetching signature from %s…
diff --git a/wallet/src/de/schildbach/wallet/service/CoinJoinService.kt b/wallet/src/de/schildbach/wallet/service/CoinJoinService.kt
index 9f14917ed8..74a9c9ac3d 100644
--- a/wallet/src/de/schildbach/wallet/service/CoinJoinService.kt
+++ b/wallet/src/de/schildbach/wallet/service/CoinJoinService.kt
@@ -116,10 +116,19 @@ class CoinJoinMixingService @Inject constructor(
const val DEFAULT_SESSIONS = 4
const val DEFAULT_DENOMINATIONS_GOAL = 50
const val DEFAULT_DENOMINATIONS_HARDCAP = 300
- const val MAX_ALLOWED_TIMESKEW = 4000L // 4 seconds
+ const val MAX_ALLOWED_AHEAD_TIMESKEW = 5000L // 5 seconds
+ const val MAX_ALLOWED_BEHIND_TIMESKEW = 20000L // 20 seconds
// these are not for production
- val FAST_MIXING_DENOMINATIONS_REMOVE = listOf() // Denomination.THOUSANDTH)
+ val FAST_MIXING_DENOMINATIONS_REMOVE = listOf() // Denomination.THOUSANDTH
+
+ fun isInsideTimeSkewBounds(timeSkew: Long): Boolean {
+ return if (timeSkew > 0) {
+ timeSkew < MAX_ALLOWED_AHEAD_TIMESKEW
+ } else {
+ (-timeSkew) < MAX_ALLOWED_BEHIND_TIMESKEW
+ }
+ }
}
private val coinJoinManager: CoinJoinManager?
@@ -148,7 +157,7 @@ class CoinJoinMixingService @Inject constructor(
private var networkStatus: NetworkStatus = NetworkStatus.UNKNOWN
private var isSynced = false
private var hasAnonymizableBalance: Boolean = false
- private var timeSkew: Long = Long.MIN_VALUE
+ private var timeSkew: Long = 0L
// https://stackoverflow.com/questions/55421710/how-to-suspend-kotlin-coroutine-until-notified
private val updateMutex = Mutex(locked = false)
@@ -292,7 +301,7 @@ class CoinJoinMixingService @Inject constructor(
this.mode = mode
this.timeSkew = timeSkew
- if (mode == CoinJoinMode.NONE || timeSkew > MAX_ALLOWED_TIMESKEW) {
+ if (mode == CoinJoinMode.NONE || !isInsideTimeSkewBounds(timeSkew)) {
updateMixingState(MixingStatus.NOT_STARTED)
} else {
configureMixing()
diff --git a/wallet/src/de/schildbach/wallet/ui/main/MainViewModel.kt b/wallet/src/de/schildbach/wallet/ui/main/MainViewModel.kt
index 73f72bdf9d..5ab0279b2b 100644
--- a/wallet/src/de/schildbach/wallet/ui/main/MainViewModel.kt
+++ b/wallet/src/de/schildbach/wallet/ui/main/MainViewModel.kt
@@ -97,17 +97,15 @@ import org.dash.wallet.common.services.analytics.AnalyticsTimer
import org.dash.wallet.common.transactions.TransactionUtils.isEntirelySelf
import org.dash.wallet.common.transactions.TransactionWrapper
import org.dash.wallet.common.transactions.TransactionWrapperComparator
-import org.dash.wallet.common.util.Constants.HTTP_CLIENT
-import org.dash.wallet.common.util.head
import org.dash.wallet.common.util.toBigDecimal
import org.dash.wallet.integrations.crowdnode.transactions.FullCrowdNodeSignUpTxSet
import org.slf4j.LoggerFactory
+import java.lang.Math.abs
import java.text.DecimalFormat
import java.util.Currency
import java.util.Locale
import javax.inject.Inject
import kotlin.collections.set
-import kotlin.math.abs
@OptIn(ExperimentalCoroutinesApi::class, FlowPreview::class)
@HiltViewModel
@@ -138,7 +136,9 @@ class MainViewModel @Inject constructor(
private const val THROTTLE_DURATION = 500L
private const val DIRECTION_KEY = "tx_direction"
private const val TIME_SKEW_TOLERANCE = 3600000 // seconds (1 hour)
- private const val TIME_SKEW_TOLERANCE_COINJOIN = 4000 // seconds
+ private const val TIME_SKEW_AHEAD_TOLERANCE_COINJOIN = 5000 // 5 seconds
+ private const val TIME_SKEW_BEHIND_TOLERANCE_COINJOIN = 20000 // 20 seconds
+
private val log = LoggerFactory.getLogger(MainViewModel::class.java)
}
@@ -392,10 +392,11 @@ class MainViewModel @Inject constructor(
val maxAllowedTimeSkew = if (coinJoinConfig.getMode() == CoinJoinMode.NONE) {
TIME_SKEW_TOLERANCE
} else {
- TIME_SKEW_TOLERANCE_COINJOIN
+ if (timeSkew > 0) TIME_SKEW_AHEAD_TOLERANCE_COINJOIN else TIME_SKEW_BEHIND_TOLERANCE_COINJOIN
}
coinJoinService.updateTimeSkew(timeSkew)
- return Pair(timeSkew > maxAllowedTimeSkew, timeSkew)
+ log.info("timeskew: {} ms", timeSkew)
+ return Pair(kotlin.math.abs(timeSkew) > maxAllowedTimeSkew, timeSkew)
} catch (ex: Exception) {
// Ignore errors
Pair(false, 0)
diff --git a/wallet/src/de/schildbach/wallet/ui/main/WalletActivityExt.kt b/wallet/src/de/schildbach/wallet/ui/main/WalletActivityExt.kt
index 301e5b4d67..28e1a68115 100644
--- a/wallet/src/de/schildbach/wallet/ui/main/WalletActivityExt.kt
+++ b/wallet/src/de/schildbach/wallet/ui/main/WalletActivityExt.kt
@@ -45,6 +45,7 @@ import org.dash.wallet.common.services.analytics.AnalyticsConstants
import org.dash.wallet.common.ui.dialogs.AdaptiveDialog
import org.dash.wallet.common.ui.dialogs.AdaptiveDialog.Companion.create
import org.dash.wallet.common.util.openCustomTab
+import kotlin.math.abs
object WalletActivityExt {
private const val STORAGE_TOLERANCE = 500 // MB
@@ -101,7 +102,7 @@ object WalletActivityExt {
if (isTimeSkewed && (!timeSkewDialogShown || coinJoinOn)) {
timeSkewDialogShown = true
// add 1 to round up so 2.2 seconds appears as 3
- showTimeSkewAlertDialog(1 + timeSkew / 1000, coinJoinOn)
+ showTimeSkewAlertDialog((if (timeSkew > 0) 1 else -1) + timeSkew / 1000L, coinJoinOn)
}
}
}
@@ -179,7 +180,8 @@ object WalletActivityExt {
R.drawable.ic_warning,
getString(R.string.wallet_timeskew_dialog_title),
if (coinJoin) {
- getString(R.string.wallet_coinjoin_timeskew_dialog_msg, diffSeconds)
+ val position = getString(if (diffSeconds > 0) R.string.timeskew_ahead else R.string.timeskew_behind)
+ getString(R.string.wallet_coinjoin_timeskew_dialog_msg, position, abs(diffSeconds))
} else {
getString(R.string.wallet_timeskew_dialog_msg, diffSeconds / 1000)
},
diff --git a/wallet/src/de/schildbach/wallet/util/TimeUtils.kt b/wallet/src/de/schildbach/wallet/util/TimeUtils.kt
index 4a9a7fef87..0d1c7fda41 100644
--- a/wallet/src/de/schildbach/wallet/util/TimeUtils.kt
+++ b/wallet/src/de/schildbach/wallet/util/TimeUtils.kt
@@ -54,5 +54,5 @@ suspend fun getTimeSkew(): Long {
requireNotNull(networkTime)
}
val systemTimeMillis = System.currentTimeMillis()
- return abs(systemTimeMillis - networkTime)
+ return systemTimeMillis - networkTime
}