Skip to content

Commit

Permalink
simplifying #2131
Browse files Browse the repository at this point in the history
  • Loading branch information
kushti committed Jul 26, 2024
1 parent cee6e3e commit b581a5b
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 93 deletions.
41 changes: 13 additions & 28 deletions src/main/scala/org/ergoplatform/http/api/BlockchainApiRoute.scala
Original file line number Diff line number Diff line change
Expand Up @@ -243,38 +243,23 @@ case class BlockchainApiRoute(readersHolder: ActorRef, ergoSettings: ErgoSetting
}

private def getBoxesByAddressUnspent(
addr: ErgoAddress,
offset: Int,
limit: Int,
sortDir: Direction,
unconfirmed: Boolean,
excludeMempoolSpent: Boolean
): Future[Seq[IndexedErgoBox]] = {

val originalLimit = limit

def fetchAndFilter(limit: Int, accumulated: Seq[IndexedErgoBox] = Seq.empty): Future[Seq[IndexedErgoBox]] = {
getHistoryWithMempool.flatMap { case (history, mempool) =>
addr: ErgoAddress,
offset: Int,
limit: Int,
sortDir: Direction,
unconfirmed: Boolean,
excludeMempoolSpent: Boolean
): Future[Seq[IndexedErgoBox]] = {

getHistoryWithMempool.map { case (history, mempool) =>
val spentBoxesIdsInMempool = if (excludeMempoolSpent) mempool.spentInputs.map(bytesToId).toSet else Set.empty[ModifierId]

val addressUtxos = getAddress(addr)(history)
getAddress(addr)(history)
.getOrElse(IndexedErgoAddress(hashErgoTree(addr.script)))
.retrieveUtxos(history, mempool, offset + accumulated.length, limit, sortDir, unconfirmed, spentBoxesIdsInMempool)

val updatedAccumulated = accumulated ++ addressUtxos
if (updatedAccumulated.length >= originalLimit || addressUtxos.length < limit) {
Future.successful(updatedAccumulated.take(originalLimit))
} else {
val maxLimit = 200
val newLimit = Math.min(limit * 2, maxLimit)
fetchAndFilter(newLimit, updatedAccumulated)
}
.retrieveUtxos(history, mempool, offset, limit, sortDir, unconfirmed, spentBoxesIdsInMempool)
}
}

fetchAndFilter(originalLimit)
}

private def validateAndGetBoxesByAddressUnspent(address: ErgoAddress,
offset: Int,
limit: Int,
Expand Down Expand Up @@ -343,7 +328,7 @@ case class BlockchainApiRoute(readersHolder: ActorRef, ergoSettings: ErgoSetting
getHistoryWithMempool.map { case (history, mempool) =>
getAddress(tree)(history)
.getOrElse(IndexedErgoAddress(hashErgoTree(tree)))
.retrieveUtxos(history, mempool, offset, limit, sortDir, unconfirmed)
.retrieveUtxos(history, mempool, offset, limit, sortDir, unconfirmed, Set.empty)
}

private def getBoxesByErgoTreeUnspentR: Route = (post & pathPrefix("box" / "unspent" / "byErgoTree") & ergoTree & paging & sortDir & unconfirmed) { (tree, offset, limit, dir, unconfirmed) =>
Expand Down Expand Up @@ -382,7 +367,7 @@ case class BlockchainApiRoute(readersHolder: ActorRef, ergoSettings: ErgoSetting
getHistoryWithMempool.map { case (history, mempool) =>
history.typedExtraIndexById[IndexedToken](uniqueId(id))
.getOrElse(IndexedToken(id))
.retrieveUtxos(history, mempool, offset, limit, sortDir, unconfirmed)
.retrieveUtxos(history, mempool, offset, limit, sortDir, unconfirmed, Set.empty)
}

private def getBoxesByTokenIdUnspentR: Route = (get & pathPrefix("box" / "unspent" / "byTokenId") & modifierId & paging & sortDir & unconfirmed) { (id, offset, limit, dir, unconfirmed) =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -237,70 +237,20 @@ abstract class Segment[T <: Segment[_] : ClassTag](val parentId: ModifierId,
def retrieveBoxes(history: ErgoHistoryReader, offset: Int, limit: Int)(implicit segmentTreshold: Int): Array[IndexedErgoBox] =
getFromSegments(history, offset, limit, boxSegmentCount, boxes, boxSegmentId, _.boxes, getBoxes)

/**
* Get a range of the boxes associated with the parent that are NOT spent
*
* @param history - history to use
* @param mempool - mempool to use, if unconfirmed is true
* @param offset - items to skip from the start
* @param limit - items to retrieve
* @param sortDir - whether to start retreival from newest box ([[DESC]]) or oldest box ([[ASC]])
* @param unconfirmed - whether to include unconfirmed boxes
* @return array of unspent boxes
*/
def retrieveUtxos(history: ErgoHistoryReader,
mempool: ErgoMemPoolReader,
offset: Int,
limit: Int,
sortDir: Direction,
unconfirmed: Boolean): Seq[IndexedErgoBox] = {
val data: ArrayBuffer[IndexedErgoBox] = ArrayBuffer.empty[IndexedErgoBox]
val confirmedBoxes: Seq[IndexedErgoBox] = sortDir match {
case DESC =>
data ++= boxes.filter(_ > 0).map(n => NumericBoxIndex.getBoxByNumber(history, n).get)
var segment: Int = boxSegmentCount
while(data.length < (limit + offset) && segment > 0) {
segment -= 1
history.typedExtraIndexById[T](idMod(boxSegmentId(parentId, segment))).get.boxes
.filter(_ > 0).map(n => NumericBoxIndex.getBoxByNumber(history, n).get) ++=: data
}
data.reverse.slice(offset, offset + limit)
case ASC =>
var segment: Int = 0
while(data.length < (limit + offset) && segment < boxSegmentCount) {
data ++= history.typedExtraIndexById[T](idMod(boxSegmentId(parentId, segment))).get.boxes
.filter(_ > 0).map(n => NumericBoxIndex.getBoxByNumber(history, n).get)
segment += 1
}
if (data.length < (limit + offset))
data ++= boxes.filter(_ > 0).map(n => NumericBoxIndex.getBoxByNumber(history, n).get)
data.slice(offset, offset + limit)
}
if(unconfirmed) {
val mempoolBoxes = filterMempool(mempool.getAll.flatMap(_.transaction.outputs))
val unconfirmedBoxes = mempoolBoxes.map(new IndexedErgoBox(0, None, None, _, 0))
sortDir match {
case DESC => unconfirmedBoxes ++ confirmedBoxes
case ASC => confirmedBoxes ++ unconfirmedBoxes
}
} else
confirmedBoxes
}


/**
* Overloaded retrieveUtxos for mempool filtering
* Get a range of the boxes associated with the parent that are NOT spent
*
* @param history - history to use
* @param mempool - mempool to use, if unconfirmed is true
* @param offset - items to skip from the start
* @param limit - items to retrieve
* @param sortDir - whether to start retreival from newest box ([[DESC]]) or oldest box ([[ASC]])
* @param unconfirmed - whether to include unconfirmed boxes
* @param spentBoxesIdsInMempool - Set of box IDs that are spent in the mempool (to be excluded if necessary)
* @return array of unspent boxes
*/
* Overloaded retrieveUtxos for mempool filtering
* Get a range of the boxes associated with the parent that are NOT spent
*
* @param history - history to use
* @param mempool - mempool to use, if unconfirmed is true
* @param offset - items to skip from the start
* @param limit - items to retrieve
* @param sortDir - whether to start retrieval from newest box ([[DESC]]) or oldest box ([[ASC]])
* @param unconfirmed - whether to include unconfirmed boxes
* @param spentBoxesIdsInMempool - Set of box IDs that are spent in the mempool (to be excluded if necessary)
* @return array of unspent boxes
*/
def retrieveUtxos(history: ErgoHistoryReader,
mempool: ErgoMemPoolReader,
offset: Int,
Expand All @@ -313,15 +263,15 @@ abstract class Segment[T <: Segment[_] : ClassTag](val parentId: ModifierId,
case DESC =>
data ++= boxes.filter(_ > 0).map(n => NumericBoxIndex.getBoxByNumber(history, n).get).filterNot(box => spentBoxesIdsInMempool.contains(box.id))
var segment: Int = boxSegmentCount
while(data.length < (limit + offset) && segment > 0) {
while (data.length < (limit + offset) && segment > 0) {
segment -= 1
history.typedExtraIndexById[T](idMod(boxSegmentId(parentId, segment))).get.boxes
.filter(_ > 0).map(n => NumericBoxIndex.getBoxByNumber(history, n).get).filterNot(box => spentBoxesIdsInMempool.contains(box.id)) ++=: data
}
data.reverse.slice(offset, offset + limit)
case ASC =>
var segment: Int = 0
while(data.length < (limit + offset) && segment < boxSegmentCount) {
while (data.length < (limit + offset) && segment < boxSegmentCount) {
data ++= history.typedExtraIndexById[T](idMod(boxSegmentId(parentId, segment))).get.boxes
.filter(_ > 0).map(n => NumericBoxIndex.getBoxByNumber(history, n).get).filterNot(box => spentBoxesIdsInMempool.contains(box.id))
segment += 1
Expand All @@ -330,7 +280,7 @@ abstract class Segment[T <: Segment[_] : ClassTag](val parentId: ModifierId,
data ++= boxes.filter(_ > 0).map(n => NumericBoxIndex.getBoxByNumber(history, n).get).filterNot(box => spentBoxesIdsInMempool.contains(box.id))
data.slice(offset, offset + limit)
}
if(unconfirmed) {
if (unconfirmed) {
val mempoolBoxes = filterMempool(mempool.getAll.flatMap(_.transaction.outputs))
val unconfirmedBoxes = mempoolBoxes.map(new IndexedErgoBox(0, None, None, _, 0)).filterNot(box => spentBoxesIdsInMempool.contains(box.id))
sortDir match {
Expand Down

0 comments on commit b581a5b

Please sign in to comment.