Android wallet v0.7.1: add ASERT difficulty support

This commit is contained in:
Vexta Project 2026-09-14 22:19:24 +00:00
commit e68f47d8d1
3 changed files with 176 additions and 2 deletions

View file

@ -23,8 +23,8 @@ android {
applicationId = "org.vextaproject.wallet" applicationId = "org.vextaproject.wallet"
minSdk = 26 minSdk = 26
targetSdk = 36 targetSdk = 36
versionCode = 39 versionCode = 40
versionName = "0.7.0" versionName = "0.7.1"
} }
signingConfigs { signingConfigs {

View file

@ -31,6 +31,8 @@ object HeaderSync {
private const val TARGET_TIMESPAN = AVERAGING_WINDOW * TARGET_SPACING private const val TARGET_TIMESPAN = AVERAGING_WINDOW * TARGET_SPACING
private const val MIN_TIMESPAN = TARGET_TIMESPAN * 92 / 100 private const val MIN_TIMESPAN = TARGET_TIMESPAN * 92 / 100
private const val MAX_TIMESPAN = TARGET_TIMESPAN * 116 / 100 private const val MAX_TIMESPAN = TARGET_TIMESPAN * 116 / 100
private const val ASERT_ACTIVATION_HEIGHT = 6500
private const val ASERT_HALF_LIFE = 2L * 24L * 60L * 60L
private val POW_LIMIT = private val POW_LIMIT =
BigInteger.ONE.shiftLeft(256).subtract(BigInteger.ONE).shiftRight(20) BigInteger.ONE.shiftLeft(256).subtract(BigInteger.ONE).shiftRight(20)
@ -329,6 +331,11 @@ object HeaderSync {
fun expectedBits(chain: List<ChainHeader>): Long { fun expectedBits(chain: List<ChainHeader>): Long {
val last = chain.last() val last = chain.last()
val nextHeight = last.height + 1
if (nextHeight >= ASERT_ACTIVATION_HEIGHT) {
return calculateAsertBits(chain)
}
if (last.height < AVERAGING_WINDOW) { if (last.height < AVERAGING_WINDOW) {
return targetToCompact(POW_LIMIT) return targetToCompact(POW_LIMIT)
@ -361,6 +368,88 @@ object HeaderSync {
return targetToCompact(newTarget) return targetToCompact(newTarget)
} }
private fun calculateAsertBits(chain: List<ChainHeader>): Long {
val last = chain.last()
val anchorHeight = ASERT_ACTIVATION_HEIGHT - 1
val anchor = chain[anchorHeight]
if (anchorHeight <= 0) {
return last.bits
}
val anchorPrevious = chain[anchorHeight - 1]
val heightDiff = last.height - anchor.height
val timeDiff = last.time - anchorPrevious.time
val idealTime = (heightDiff + 1L) * TARGET_SPACING
val exponent =
((timeDiff - idealTime) * 65536L) / ASERT_HALF_LIFE
var shifts = exponent shr 16
val frac = (exponent and 0xffffL)
val fracBig = BigInteger.valueOf(frac)
val factor =
BigInteger.valueOf(65536L)
.add(
BigInteger.valueOf(195766423245049L)
.multiply(fracBig)
.add(
BigInteger.valueOf(971821376L)
.multiply(fracBig.pow(2))
)
.add(
BigInteger.valueOf(5127L)
.multiply(fracBig.pow(3))
)
.add(BigInteger.ONE.shiftLeft(47))
.shiftRight(48)
)
.toLong()
var target =
compactToTarget(anchor.bits)
.multiply(BigInteger.valueOf(factor))
shifts -= 16
if (shifts <= 0) {
val rightShift = -shifts
target =
if (rightShift >= 256) {
BigInteger.ONE
} else {
target.shiftRight(rightShift.toInt())
}
} else {
if (shifts >= 256) {
target = POW_LIMIT
} else {
val maxBeforeShift = POW_LIMIT.shiftRight(shifts.toInt())
target =
if (target > maxBeforeShift) {
POW_LIMIT
} else {
target.shiftLeft(shifts.toInt())
}
}
}
if (target <= BigInteger.ZERO) {
target = BigInteger.ONE
}
if (target > POW_LIMIT) {
target = POW_LIMIT
}
return targetToCompact(target)
}
fun medianTimePast( fun medianTimePast(
chain: List<ChainHeader>, chain: List<ChainHeader>,
height: Int height: Int

View file

@ -40,6 +40,8 @@ class MainActivity : Activity() {
private const val TARGET_TIMESPAN = AVERAGING_WINDOW * TARGET_SPACING private const val TARGET_TIMESPAN = AVERAGING_WINDOW * TARGET_SPACING
private const val MIN_TIMESPAN = TARGET_TIMESPAN * 92 / 100 private const val MIN_TIMESPAN = TARGET_TIMESPAN * 92 / 100
private const val MAX_TIMESPAN = TARGET_TIMESPAN * 116 / 100 private const val MAX_TIMESPAN = TARGET_TIMESPAN * 116 / 100
private const val ASERT_ACTIVATION_HEIGHT = 6500
private const val ASERT_HALF_LIFE = 2L * 24L * 60L * 60L
private val POW_LIMIT = private val POW_LIMIT =
BigInteger.ONE.shiftLeft(256).subtract(BigInteger.ONE).shiftRight(20) BigInteger.ONE.shiftLeft(256).subtract(BigInteger.ONE).shiftRight(20)
@ -470,6 +472,11 @@ class MainActivity : Activity() {
private fun expectedBits(chain: List<ChainHeader>): Long { private fun expectedBits(chain: List<ChainHeader>): Long {
val last = chain.last() val last = chain.last()
val nextHeight = last.height + 1
if (nextHeight >= ASERT_ACTIVATION_HEIGHT) {
return calculateAsertBits(chain)
}
if (last.height < AVERAGING_WINDOW) { if (last.height < AVERAGING_WINDOW) {
return targetToCompact(POW_LIMIT) return targetToCompact(POW_LIMIT)
@ -502,6 +509,84 @@ class MainActivity : Activity() {
return targetToCompact(newTarget) return targetToCompact(newTarget)
} }
private fun calculateAsertBits(chain: List<ChainHeader>): Long {
val last = chain.last()
val anchorHeight = ASERT_ACTIVATION_HEIGHT - 1
val anchor = chain[anchorHeight]
val anchorPrevious = chain[anchorHeight - 1]
val heightDiff = last.height - anchor.height
val timeDiff = last.time - anchorPrevious.time
val idealTime = (heightDiff + 1L) * TARGET_SPACING
val exponent =
((timeDiff - idealTime) * 65536L) / ASERT_HALF_LIFE
var shifts = exponent shr 16
val frac = exponent and 0xffffL
val fracBig = BigInteger.valueOf(frac)
val factor =
BigInteger.valueOf(65536L)
.add(
BigInteger.valueOf(195766423245049L)
.multiply(fracBig)
.add(
BigInteger.valueOf(971821376L)
.multiply(fracBig.pow(2))
)
.add(
BigInteger.valueOf(5127L)
.multiply(fracBig.pow(3))
)
.add(BigInteger.ONE.shiftLeft(47))
.shiftRight(48)
)
.toLong()
var target =
compactToTarget(anchor.bits)
.multiply(BigInteger.valueOf(factor))
shifts -= 16
if (shifts <= 0) {
val rightShift = -shifts
target =
if (rightShift >= 256) {
BigInteger.ONE
} else {
target.shiftRight(rightShift.toInt())
}
} else {
if (shifts >= 256) {
target = POW_LIMIT
} else {
val maxBeforeShift =
POW_LIMIT.shiftRight(shifts.toInt())
target =
if (target > maxBeforeShift) {
POW_LIMIT
} else {
target.shiftLeft(shifts.toInt())
}
}
}
if (target <= BigInteger.ZERO) {
target = BigInteger.ONE
}
if (target > POW_LIMIT) {
target = POW_LIMIT
}
return targetToCompact(target)
}
private fun medianTimePast( private fun medianTimePast(
chain: List<ChainHeader>, chain: List<ChainHeader>,
height: Int height: Int