Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

switch address to ergo-tree #7

Merged
merged 1 commit into from
Jun 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
package org.ergoplatform.uexplorer.plugin.alert

import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource
import org.ergoplatform.uexplorer.{SortedTopAddressMap, Storage}
import org.ergoplatform.uexplorer.Storage
import org.ergoplatform.uexplorer.plugin.alert.HighValueDetector.{BlockMatch, TxMatch}

trait Analyzer {

def trackTx(
txMatch: TxMatch,
utxoState: Storage,
graphTraversalSource: Option[GraphTraversalSource]
txMatch: TxMatch,
utxoState: Storage,
graphTraversalSource: Option[GraphTraversalSource]
): Option[TxMatch]

def trackBlock(
blockMatch: BlockMatch,
utxoState: Storage,
graphTraversalSource: Option[GraphTraversalSource]
blockMatch: BlockMatch,
utxoState: Storage,
graphTraversalSource: Option[GraphTraversalSource]
): Option[BlockMatch]

}
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
package org.ergoplatform.uexplorer.plugin.alert

import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource
import org.ergoplatform.uexplorer.Storage
import org.ergoplatform.uexplorer.db.BestBlockInserted
import org.ergoplatform.uexplorer.node.ApiTransaction
import org.ergoplatform.uexplorer.plugin.alert.Detector.AlertMessage
import org.ergoplatform.uexplorer.plugin.alert.HighValueDetector.{BlockMatch, TxMatch}
import org.ergoplatform.uexplorer.{Address, BoxId, SortedTopAddressMap, Storage, TopAddressMap}

trait Detector {

def inspectNewPoolTx(
tx: ApiTransaction,
utxoState: Storage,
graphTraversalSource: Option[GraphTraversalSource]
tx: ApiTransaction,
utxoState: Storage,
graphTraversalSource: Option[GraphTraversalSource]
): List[TxMatch]

def inspectNewBlock(
newBlock: BestBlockInserted,
utxoState: Storage,
graphTraversalSource: Option[GraphTraversalSource]
newBlock: BestBlockInserted,
utxoState: Storage,
graphTraversalSource: Option[GraphTraversalSource]
): List[BlockMatch]
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import discord4j.core.{DiscordClient, GatewayDiscordClient}
import discord4j.core.`object`.entity.Message
import discord4j.core.`object`.entity.channel.MessageChannel
import org.ergoplatform.uexplorer.db.FullBlock
import org.ergoplatform.uexplorer.{Address, BoxId, TxId}
import org.ergoplatform.uexplorer.{ErgoTreeHex, BoxId, TxId}
import org.ergoplatform.uexplorer.node.ApiTransaction
import org.ergoplatform.uexplorer.plugin.Plugin
import org.slf4j.{Logger, LoggerFactory}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,29 +21,29 @@ class HighValueDetector(txErgValueThreshold: Long, blockErgValueThreshold: Long)
storage: Storage,
graphTraversalSource: Option[GraphTraversalSource]
): List[TxMatch] = {
def sumAddressValues(addresses: Set[Address]): Map[Address, Address.State] =
addresses
.flatMap(a => storage.getUtxosByAddress(a).map(a -> _))
.foldLeft(Map.empty[Address, Address.State]) { case (acc, (address, valueByBox)) =>
acc.updated(address, Address.State(valueByBox.values.asScala.sum))
def sumErgoTreeValues(ergoTrees: Set[ErgoTreeHex]): Map[ErgoTreeHex, ErgoTreeHex.State] =
ergoTrees
.flatMap(a => storage.getUtxosByErgoTreeHex(a).map(a -> _))
.foldLeft(Map.empty[ErgoTreeHex, ErgoTreeHex.State]) { case (acc, (ergoTree, valueByBox)) =>
acc.updated(ergoTree, ErgoTreeHex.State(valueByBox.values.asScala.sum))
}

val outputsWithoutPaybacksAndFees =
tx.outputs.filterNot(o =>
tx.inputs.exists(i =>
storage.getAddressByUtxo(i.boxId).contains(o.address)
) || o.address == Const.FeeContract.address
storage.getErgoTreeHexByUtxo(i.boxId).contains(o.ergoTree)
) || o.ergoTree == Const.FeeContract.address
)
Option(outputsWithoutPaybacksAndFees.iterator.map(_.value).sum)
.filter(_ >= txErgValueThreshold * Const.NanoOrder)
.map { value =>
val inputAddresses = tx.inputs.iterator.map(_.boxId).flatMap(storage.getAddressByUtxo).toSet
val inputValueByAddress = sumAddressValues(inputAddresses)
val outputAddresses = outputsWithoutPaybacksAndFees.iterator.map(_.address).toSet
val outputValueByAddress = sumAddressValues(outputAddresses)
val txMatch = TxMatch(tx, value, inputValueByAddress, outputValueByAddress)
val inputErgoTrees = tx.inputs.iterator.map(_.boxId).flatMap(storage.getErgoTreeHexByUtxo).toSet
val inputValueByErgoTree = sumErgoTreeValues(inputErgoTrees)
val outputErgoTrees = outputsWithoutPaybacksAndFees.iterator.map(_.ergoTree).toSet
val outputValueByErgoTree = sumErgoTreeValues(outputErgoTrees)
val txMatch = TxMatch(tx, value, inputValueByErgoTree, outputValueByErgoTree)
Either.cond(
inputValueByAddress.valuesIterator.map(_._1).sum >= value,
inputValueByErgoTree.valuesIterator.map(_._1).sum >= value,
txMatch,
txMatch
)
Expand Down Expand Up @@ -72,26 +72,26 @@ object HighValueDetector {
case class BlockMatch(
block: FullBlock,
blockValue: Value,
inputs: Map[Address, Address.State],
outputs: Map[Address, Address.State]
inputs: Map[ErgoTreeHex, ErgoTreeHex.State],
outputs: Map[ErgoTreeHex, ErgoTreeHex.State]
)

case class TxMatch(
tx: ApiTransaction,
txValue: Value,
inputs: Map[Address, Address.State],
outputs: Map[Address, Address.State]
inputs: Map[ErgoTreeHex, ErgoTreeHex.State],
outputs: Map[ErgoTreeHex, ErgoTreeHex.State]
) {

override def toString: AlertMessage = {
val fmtValue = valueFormat.format(txValue / Const.NanoOrder)
val fmtInputAddrSum = valueFormat.format(inputs.valuesIterator.map(_._1).sum / Const.NanoOrder)
val fmtOutputAddrSum = valueFormat.format(outputs.valuesIterator.map(_._1).sum / Const.NanoOrder)

def stringify(tuple: (Address, Address.State)) = tuple match {
case (address, Address.State(value)) =>
def stringify(tuple: (ErgoTreeHex, ErgoTreeHex.State)) = tuple match {
case (ergoTree, ErgoTreeHex.State(value)) =>
val fmtVal = valueFormat.format(value / Const.NanoOrder)
s"${address.asInstanceOf[String].take(5)} $fmtVal"
s"${ergoTree.asInstanceOf[String].take(5)} $fmtVal"
}

val addressDetails =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package org.ergoplatform.uexplorer.plugin.alert

import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource
import org.apache.tinkerpop.gremlin.structure.io.graphml.GraphMLWriter
import org.ergoplatform.uexplorer.{SortedTopAddressMap, Storage}
import org.ergoplatform.uexplorer.Storage
import org.ergoplatform.uexplorer.plugin.alert.HighValueDetector.{BlockMatch, TxMatch}

import java.io.FileOutputStream
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import com.typesafe.scalalogging.LazyLogging
import eu.timepit.refined.auto.*
import org.ergoplatform.uexplorer.{MapPimp, MutableMapPimp}
import org.ergoplatform.uexplorer.cassandra.{CassandraBackend, CassandraPersistenceSupport}
import org.ergoplatform.uexplorer.{Address, BlockId, BoxId}
import org.ergoplatform.uexplorer.{ErgoTreeHex, BlockId, BoxId}
import org.ergoplatform.uexplorer.cassandra
import scala.collection.compat.immutable.ArraySeq
import scala.collection.immutable.{ArraySeq, TreeMap, TreeSet}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import org.ergoplatform.uexplorer.indexer.mempool.MempoolStateHolder.*
import org.ergoplatform.uexplorer.indexer.mempool.{MempoolStateHolder, MempoolSyncer}
import org.ergoplatform.uexplorer.indexer.plugin.PluginManager
import org.ergoplatform.uexplorer.plugin.Plugin
import org.ergoplatform.uexplorer.{Address, BoxId, Const}
import org.slf4j.LoggerFactory

import java.io.{PrintWriter, StringWriter}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package org.ergoplatform.uexplorer.indexer

import org.ergoplatform.uexplorer.Const.MinerRewardDelta
import org.ergoplatform.uexplorer.{Address, HexString}
import org.ergoplatform.uexplorer.{ErgoTreeHex, HexString}
import org.ergoplatform.ErgoScriptPredef
import scorex.util.encode.{Base16, Base58}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ class BlockIndexer(

def addBestBlock(block: LinkedBlock): Try[BestBlockInserted] =
for {
lb <- UtxoTracker(block, storage.getAddressByUtxo, storage.getUtxoValueByAddress)
lb <- UtxoTracker(block, storage.getErgoTreeHexByUtxo, storage.getUtxoValueByErgoTreeHex)
_ <- storage.persistNewBlock(lb)
_ <- if (lb.info.height % mvStoreConf.heightCompactRate == 0) compact(true) else Success(())
} yield BestBlockInserted(lb, None) // TODO we forgot about FullBlock !
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import eu.timepit.refined.refineV
import org.ergoplatform.ErgoAddressEncoder
import org.ergoplatform.mining.emission.EmissionRules
import org.ergoplatform.settings.MonetarySettings
import org.ergoplatform.uexplorer.{Address, NetworkPrefix}
import pureconfig.ConfigReader.Result
import pureconfig.error.CannotConvert
import pureconfig.{ConfigReader, ConfigSource}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import com.typesafe.scalalogging.LazyLogging
import org.ergoplatform.uexplorer.http.BlockHttpClient
import org.ergoplatform.uexplorer.indexer.mempool.MempoolStateHolder.*
import org.ergoplatform.uexplorer.node.ApiTransaction
import org.ergoplatform.uexplorer.{Address, BoxId, TxId}
import org.ergoplatform.uexplorer.{ErgoTreeHex, BoxId, TxId}

import scala.collection.immutable.{ArraySeq, ListMap}
import scala.concurrent.Future
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSo
import org.ergoplatform.uexplorer.db.{BestBlockInserted, FullBlock}
import org.ergoplatform.uexplorer.indexer.mempool.MempoolStateHolder.MempoolStateChanges
import org.ergoplatform.uexplorer.plugin.Plugin
import org.ergoplatform.uexplorer.{SortedTopAddressMap, Storage}
import org.ergoplatform.uexplorer.Storage

import java.util.ServiceLoader
import scala.concurrent.ExecutionContext.Implicits.global
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@ object Const {
val address: Address = Address.fromStringUnsafe(
"2Z4YBkDsDvQj8BX7xiySFewjitqp2ge9c99jfes2whbtKitZTxdBYqbrVZUvZvKv6aqn9by4kp3LE1c26LCyosFnVnm6b6U1JYvWpYmL2ZnixJbXLjWAWuBThV1D6dLpqZJYQHYDznJCk49g5TUiS4q8khpag2aNmHwREV7JSsypHdHLgJT7MGaw51aJfNubyzSKxZ4AJXFS27EfXwyCLzW1K6GVqwkJtCoPvrcLqmqwacAWJPkmh78nke9H4oT88XmSbRt2n9aWZjosiZCafZ4osUDxmZcc5QVEeTWn8drSraY3eFKe8Mu9MSCcVU"
)
def ergoTreeHex(implicit enc: ErgoAddressEncoder): Try[HexString] = ErgoTreeParser.base58Address2ErgoTreeHex(address)
val ergoTree: HexString = HexString.fromStringUnsafe(
"101004020e36100204a00b08cd0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798ea02d192a39a8cc7a7017300730110010204020404040004c0fd4f05808c82f5f6030580b8c9e5ae040580f882ad16040204c0944004c0f407040004000580f882ad16d19683030191a38cc7a7019683020193c2b2a57300007473017302830108cdeeac93a38cc7b2a573030001978302019683040193b1a5730493c2a7c2b2a573050093958fa3730673079973089c73097e9a730a9d99a3730b730c0599c1a7c1b2a5730d00938cc7b2a5730e0001a390c1a7730f"
)
}

object Foundation {
Expand All @@ -34,15 +36,16 @@ object Const {
val address: Address = Address.fromStringUnsafe(
"4L1ktFSzm3SH1UioDuUf5hyaraHird4D2dEACwQ1qHGjSKtA6KaNvSzRCZXZGf9jkfNAEC1SrYaZmCuvb2BKiXk5zW9xuvrXFT7FdNe2KqbymiZvo5UQLAm5jQY8ZBRhTZ4AFtZa1UF5nd4aofwPiL7YkJuyiL5hDHMZL1ZnyL746tHmRYMjAhCgE7d698dRhkdSeVy"
)

def ergoTreeHex(implicit enc: ErgoAddressEncoder): Try[HexString] = ErgoTreeParser.base58Address2ErgoTreeHex(address)
val ergoTree: HexString = HexString.fromStringUnsafe(
"100e040004c094400580809cde91e7b0010580acc7f03704be944004808948058080c7b7e4992c0580b4c4c32104fe884804c0fd4f0580bcc1960b04befd4f05000400ea03d192c1b2a5730000958fa373019a73029c73037e997304a305958fa373059a73069c73077e997308a305958fa373099c730a7e99730ba305730cd193c2a7c2b2a5730d00d5040800"
)
}

object NoPremine {
val initialNanoErgs: Long = 1 * CoinsInOneErgo
val box: BoxId = BoxId("b8ce8cfe331e5eadfb0783bdc375c94413433f65e1e45857d71550d42e4d83bd")
val address: Address = Address.fromStringUnsafe("4MQyMKvMbnCJG3aJ")
def ergoTreeHex(implicit enc: ErgoAddressEncoder): Try[HexString] = ErgoTreeParser.base58Address2ErgoTreeHex(address)
val initialNanoErgs: Long = 1 * CoinsInOneErgo
val box: BoxId = BoxId("b8ce8cfe331e5eadfb0783bdc375c94413433f65e1e45857d71550d42e4d83bd")
val address: Address = Address.fromStringUnsafe("4MQyMKvMbnCJG3aJ")
val ergoTree: HexString = HexString.fromStringUnsafe("10010100d17300")
}
}

Expand All @@ -55,10 +58,9 @@ object Const {
"2iHkR7CWvD1R4j1yZg5bkeDRQavjAaVPeTDFGGLZduHyfWMuYpmhHocX8GJoaieTx78FntzJbCBVL6rf96ocJoZdmWBL2fci7NqWgAirppPQmZ7fN9V6z13Ay6brPriBKYqLp1bT2Fk4FkFLCfdPpe"
)

def ergoTree(implicit enc: ErgoAddressEncoder): Try[HexString] = ErgoTreeParser.base58Address2ErgoTreeHex(FeeContract.address)

val ergoTreeTemplateHash =
"5b710d70f207f03745a8bb713006f235446f0104f89e977ae066ae184c0494fa"
val ergoTree: HexString = HexString.fromStringUnsafe(
"1005040004000e36100204a00b08cd0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798ea02d192a39a8cc7a701730073011001020402d19683030193a38cc7b2a57300000193c2b2a57301007473027303830108cdeeac93b1a57304"
)
}

val EpochLength = 1024
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ import org.ergoplatform.settings.MonetarySettings
import org.ergoplatform.mining.emission.EmissionRules
import org.ergoplatform.ErgoAddressEncoder
import pureconfig.ConfigReader
import pureconfig._
import pureconfig.generic.derivation.default._
import pureconfig.*
import pureconfig.generic.derivation.default.*

final case class ProtocolSettings(
networkPrefix: NetworkPrefix,
genesisAddress: Address,
) derives ConfigReader {
networkPrefix: NetworkPrefix,
genesisAddress: Address
) derives ConfigReader {

val monetary = MonetarySettings()
val emission = new EmissionRules(monetary)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package org.ergoplatform.uexplorer

import org.ergoplatform.uexplorer.db.BlockInfo
import org.ergoplatform.uexplorer.{Address, BlockId, BoxId, Height, Value}
import org.ergoplatform.uexplorer.{BlockId, BoxId, ErgoTreeHex, Height, Value}

import scala.collection.immutable.TreeSet
import scala.collection.concurrent
Expand All @@ -27,9 +27,9 @@ trait Storage {

def getBlocksByHeight(atHeight: Height): Map[BlockId, BlockInfo]

def getAddressByUtxo(boxId: BoxId): Option[Address]
def getErgoTreeHexByUtxo(boxId: BoxId): Option[ErgoTreeHex]

def getUtxosByAddress(address: Address): Option[java.util.Map[BoxId, Value]]
def getUtxosByErgoTreeHex(ergoTreeHex: ErgoTreeHex): Option[java.util.Map[BoxId, Value]]

def getUtxoValueByAddress(address: Address, utxo: BoxId): Option[Value]
def getUtxoValueByErgoTreeHex(ergoTreeHex: ErgoTreeHex, utxo: BoxId): Option[Value]
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,6 @@ import org.ergoplatform.uexplorer.node.*
import scala.collection.immutable.ArraySeq
import org.ergoplatform.uexplorer.*

case class OutputRecord(
txId: TxId,
boxId: BoxId,
ergoTree: HexString,
templateHashHex: TemplateHashHex,
address: Address,
value: Value,
additionalRegisters: Map[RegisterId, ExpandedRegister]
)

case class InputRecord(
txId: TxId,
boxId: BoxId,
address: Address,
value: Value
)
case class MinerRewardInfo(reward: MinerReward, fee: MinerFee, address: Address)

case class BlockWithReward(
b: ApiFullBlock,
minerRewardInfo: MinerRewardInfo
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package org.ergoplatform.uexplorer.db

import org.ergoplatform.uexplorer.Const.Protocol
import org.ergoplatform.uexplorer.Const.Protocol.Emission
import org.ergoplatform.uexplorer.{Address, BlockId, ProtocolSettings, Revision}
import org.ergoplatform.uexplorer.{Address, BlockId, ErgoTreeHex, ProtocolSettings, Revision}

final case class BlockInfo(
revision: Revision,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,25 @@ import sigmastate.serialization.{GroupElementSerializer, SigmaSerializer}
import scala.collection.immutable.ArraySeq
import scala.util.Try

case class OutputRecord(
txId: TxId,
boxId: BoxId,
ergoTree: ErgoTreeHex,
templateHashHex: Option[TemplateHashHex],
value: Value,
additionalRegisters: Map[RegisterId, ExpandedRegister]
)

object OutputBuilder {

private def getOutputRecords(block: BlockWithReward)(implicit enc: ErgoAddressEncoder): Try[ArraySeq[OutputRecord]] = Try {
block.b.transactions.transactions.flatMap { tx =>
tx.outputs.map { o =>
(
for {
address <- ErgoTreeParser.ergoTreeHex2Base58Address(o.ergoTree)
scriptTemplateHash <- ErgoTreeParser.ergoTreeHex2ErgoTreeTemplateSha256Hex(o.ergoTree)
additionalRegisters = o.additionalRegisters.view.mapValues(hex => RegistersParser.parseAny(hex)).toMap
} yield OutputRecord(tx.id, o.boxId, o.ergoTree, scriptTemplateHash, address, o.value, additionalRegisters)
} yield OutputRecord(tx.id, o.boxId, o.ergoTree, scriptTemplateHash, o.value, additionalRegisters)
).get
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import eu.timepit.refined.auto.*
import scala.collection.immutable.ArraySeq
import scala.util.Try

case class MinerRewardInfo(reward: MinerReward, fee: MinerFee, address: Address)

object RewardCalculator {

// CPU greedy (2% of all runtime)
Expand Down
Loading