Skip to content

Commit

Permalink
Merge pull request #12 from Constellation-Labs/main
Browse files Browse the repository at this point in the history
Merging main to testnet
  • Loading branch information
IPadawans authored Nov 1, 2023
2 parents 47c4609 + 3f76c53 commit 70674cd
Show file tree
Hide file tree
Showing 6 changed files with 67 additions and 65 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,11 @@ import org.tessellation.schema.transaction.{RewardTransaction, TransactionAmount
object BountyRewards {
private val logger = LoggerFactory.getLogger("BountyRewards")

private def getDeviceBountiesRewards(device: DeviceInfo, currentEpochProgress: Long, lastBalances: Map[Address, Balance]): Long = {
private def getDeviceBountiesRewards(device: DeviceInfo, currentEpochProgress: Long, collateralMultiplierFactor: Double): Long = {
val deviceBountiesRewardsAmount = getDeviceBountyRewardsAmount(device, currentEpochProgress)
device.dorAPIResponse.rewardAddress match {
case Some(rewardAddress) => calculateBountiesRewardsWithCollateral(lastBalances, rewardAddress, deviceBountiesRewardsAmount)
case None =>
logger.warn(s"Could not get bounty rewards, nullable reward address!")
0L
}
val rewardsWithCollateral = deviceBountiesRewardsAmount * collateralMultiplierFactor

rewardsWithCollateral.toLong
}

def getDeviceBountyRewardsAmount(device: DeviceInfo, currentEpochProgress: Long): Long = {
Expand All @@ -44,32 +41,14 @@ object BountyRewards {
0L
}

def calculateBountiesRewardsWithCollateral(lastBalances: Map[Address, Balance], rewardAddress: Address, deviceTotalRewards: Long): Long = {
val updatedBalance = lastBalances.get(rewardAddress) match {
case Some(rewardAddressBalance) =>
val balance = rewardAddressBalance.value.value
if (balance < COLLATERAL_50K) {
deviceTotalRewards * COLLATERAL_LESS_THAN_50K_MULTIPLIER
} else if (balance >= COLLATERAL_50K && balance < COLLATERAL_100K) {
deviceTotalRewards * COLLATERAL_BETWEEN_50K_AND_100K_MULTIPLIER
} else if (balance >= COLLATERAL_100K && balance < COLLATERAL_200K) {
deviceTotalRewards * COLLATERAL_BETWEEN_100K_AND_200K_MULTIPLIER
} else {
deviceTotalRewards * COLLATERAL_GREATER_THAN_200K_MULTIPLIER
}
case None => deviceTotalRewards.toDouble
}

updatedBalance.toLong
}

def getTaxesToValidatorNodes(deviceTotalRewards: Long): Long = {
(deviceTotalRewards * 0.1).toLong
}

def getBountyRewardsTransactions(state: CheckInDataCalculatedState, currentEpochProgress: Long, lastBalances: Map[Address, Balance]): (List[RewardTransaction], Long) = {
def getBountyRewardsTransactions(state: CheckInDataCalculatedState, currentEpochProgress: Long, lastBalancesRaw: Map[Address, Balance]): (List[RewardTransaction], Long) = {
var taxesToValidatorNodes = 0L
val allRewards: Map[Address, RewardTransaction] = Map.empty
var lastBalances = lastBalancesRaw.map { case (address, balance) => address -> balance.value.value }

val rewardsTransactions = state.devices.foldLeft(allRewards) { case (acc, (_, value)) =>
value.dorAPIResponse.rewardAddress match {
Expand All @@ -81,7 +60,11 @@ object BountyRewards {
logger.warn(s"Device with reward address ${rewardAddress.value.value} didn't make a check in in the last 24 hours")
acc
} else {
val deviceTotalRewards = getDeviceBountiesRewards(value, currentEpochProgress, lastBalances)
val deviceCollateral = getDeviceCollateral(lastBalances, rewardAddress)
lastBalances = deviceCollateral._1
val collateralMultiplierFactor = deviceCollateral._2

val deviceTotalRewards = getDeviceBountiesRewards(value, currentEpochProgress, collateralMultiplierFactor)
val deviceTaxToValidatorNodes = getTaxesToValidatorNodes(deviceTotalRewards)
val rewardValue = deviceTotalRewards - deviceTaxToValidatorNodes
taxesToValidatorNodes += deviceTaxToValidatorNodes
Expand All @@ -107,4 +90,25 @@ object BountyRewards {

(rewardsTransactions, taxesToValidatorNodes)
}

def getDeviceCollateral(lastBalances: Map[Address, Long], rewardAddress: Address): (Map[Address, Long], Double) = {
lastBalances.get(rewardAddress) match {
case None => (lastBalances, COLLATERAL_LESS_THAN_50K_MULTIPLIER)
case Some(balance) =>
val (value, collateralMultiplierFactor) = if (balance < COLLATERAL_50K) {
(balance, COLLATERAL_LESS_THAN_50K_MULTIPLIER)
} else if (balance >= COLLATERAL_50K && balance < COLLATERAL_100K) {
(balance, COLLATERAL_BETWEEN_50K_AND_100K_MULTIPLIER)
} else if (balance >= COLLATERAL_100K && balance < COLLATERAL_200K) {
(balance, COLLATERAL_BETWEEN_100K_AND_200K_MULTIPLIER)
} else {
(toTokenAmountFormat(200000), COLLATERAL_GREATER_THAN_200K_MULTIPLIER)
}

val updatedBalance = balance - value
val updatedLastBalances = lastBalances + (rewardAddress -> updatedBalance)

(updatedLastBalances, collateralMultiplierFactor)
}
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.my.dor_metagraph.l0

import cats.effect.{IO, Resource}
import com.my.dor_metagraph.l0.rewards.BountyRewards.{calculateBountiesRewardsWithCollateral, getDeviceBountyRewardsAmount, getTaxesToValidatorNodes}
import com.my.dor_metagraph.l0.rewards.BountyRewards.{getDeviceBountyRewardsAmount, getDeviceCollateral, getTaxesToValidatorNodes}
import com.my.dor_metagraph.l0.rewards.MainRewards
import com.my.dor_metagraph.l0.rewards.ValidatorNodesRewards.getValidatorNodesTransactions
import com.my.dor_metagraph.shared_data.types.Types.{CheckInDataCalculatedState, DeviceInfo, DorAPIResponse}
Expand Down Expand Up @@ -80,7 +80,7 @@ object DorMetagraphRewardsTest extends MutableIOSuite {
currentAddress2 -> DeviceInfo(1693526401L, currentDeviceInfoAPIResponse, currentEpochProgress)
))

val balances = Map(currentAddress -> Balance(NonNegLong.unsafeFrom(toTokenAmountFormat(200000))))
val balances = Map(currentAddress -> Balance(NonNegLong.unsafeFrom(toTokenAmountFormat(210000))))

val rewardsIO = MainRewards.buildRewards(state, currentEpochProgress, balances, getValidatorNodesL0, getValidatorNodesL1)
val rewardIO = rewardsIO.map(rewards => rewards.find(reward => reward.destination == currentAddress))
Expand All @@ -89,9 +89,9 @@ object DorMetagraphRewardsTest extends MutableIOSuite {
rewards <- rewardsIO
reward <- rewardIO
} yield expect.eql(7, rewards.size) &&
expect.eql(10800000000L, reward.get.amount.value.value) &&
expect.eql(9900000000L, reward.get.amount.value.value) &&
expect.eql(currentAddress, reward.get.destination) &&
expect.eql(10800000000L, rewards.toList(1).amount.value.value)
expect.eql(9900000000L, rewards.toList(1).amount.value.value)
}

test("Build correctly rewards - CommercialLocationBounty") {
Expand Down Expand Up @@ -167,46 +167,44 @@ object DorMetagraphRewardsTest extends MutableIOSuite {
val currentAddress = Address.fromBytes("DAG0DQPuvVThrHnz66S4V6cocrtpg59oesAWyRMb".getBytes)
val balance = toTokenAmountFormat(10)

val balances = Map(currentAddress -> Balance(NonNegLong.unsafeFrom(balance)))
val bountiesWithCollateral = calculateBountiesRewardsWithCollateral(balances, currentAddress, balance)
val balances = Map(currentAddress -> balance)
val bountiesWithCollateral = getDeviceCollateral(balances, currentAddress)

expect.eql(1000000000L, bountiesWithCollateral)
expect.eql(1.0, bountiesWithCollateral._2) &&
expect.eql(0L, bountiesWithCollateral._1(currentAddress))
}

pureTest("Calculate values with collateral: > 50K and < 100K") {
val currentAddress = Address.fromBytes("DAG0DQPuvVThrHnz66S4V6cocrtpg59oesAWyRMb".getBytes)
val balance = toTokenAmountFormat(70000)

val balances = Map(currentAddress -> Balance(NonNegLong.unsafeFrom(balance)))
val bountiesWithCollateral = calculateBountiesRewardsWithCollateral(balances, currentAddress, balance)
val balances = Map(currentAddress -> balance)
val bountiesWithCollateral = getDeviceCollateral(balances, currentAddress)

expect.eql(7350000000000L, bountiesWithCollateral)
expect.eql(1.05, bountiesWithCollateral._2) &&
expect.eql(0L, bountiesWithCollateral._1(currentAddress))
}

pureTest("Calculate values with collateral: > 100K and < 200K") {
val currentAddress = Address.fromBytes("DAG0DQPuvVThrHnz66S4V6cocrtpg59oesAWyRMb".getBytes)
val balance = toTokenAmountFormat(150000)

val balances = Map(currentAddress -> Balance(NonNegLong.unsafeFrom(balance)))
val bountiesWithCollateral = calculateBountiesRewardsWithCollateral(balances, currentAddress, balance)
val balances = Map(currentAddress -> balance)
val bountiesWithCollateral = getDeviceCollateral(balances, currentAddress)

expect.eql(16500000000000L, bountiesWithCollateral)
expect(1.1 == bountiesWithCollateral._2) &&
expect.eql(0L, bountiesWithCollateral._1(currentAddress))
}

pureTest("Calculate values with collateral: > 200K") {
val currentAddress = Address.fromBytes("DAG0DQPuvVThrHnz66S4V6cocrtpg59oesAWyRMb".getBytes)
val balance = toTokenAmountFormat(210000)

val balances = Map(currentAddress -> Balance(NonNegLong.unsafeFrom(balance)))
val bountiesWithCollateral = calculateBountiesRewardsWithCollateral(balances, currentAddress, balance)

expect.eql(25200000000000L, bountiesWithCollateral)
}

pureTest("Successfully get taxed to validator nodes") {
val taxes = getTaxesToValidatorNodes(10000)
val balances = Map(currentAddress -> balance)
val bountiesWithCollateral = getDeviceCollateral(balances, currentAddress)

expect.eql(1000, taxes)
expect(1.2 == bountiesWithCollateral._2) &&
expect.eql(1000000000000L, bountiesWithCollateral._1(currentAddress))
}

pureTest("Build validator nodes rewards successfully") {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,19 @@ import cats.effect.IO
import com.my.dor_metagraph.shared_data.types.Types.CheckInDataCalculatedState
import eu.timepit.refined.types.numeric.NonNegLong
import io.circe.syntax.EncoderOps
import org.slf4j.LoggerFactory
import org.tessellation.schema.SnapshotOrdinal
import org.tessellation.security.hash.Hash

import java.security.MessageDigest

object CalculatedState {
private val logger = LoggerFactory.getLogger("CalculatedState")

private var maybeCheckInCalculatedState: (SnapshotOrdinal, CheckInDataCalculatedState) = (
SnapshotOrdinal(NonNegLong(0L)),
CheckInDataCalculatedState(Map.empty)
)

def getCalculatedState: IO[(SnapshotOrdinal, CheckInDataCalculatedState)] = {
logger.info(s"GETTING CALCULATED STATE: $maybeCheckInCalculatedState")
IO(maybeCheckInCalculatedState)
}

Expand All @@ -35,8 +32,6 @@ object CalculatedState {
CheckInDataCalculatedState(updatedDevices)
)

logger.info(s"SETTING CALCULATED STATE, NEW STATE: $maybeCheckInCalculatedState CURRENT ORDINAL: ${snapshotOrdinal}")

IO(true)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,16 @@ package com.my.dor_metagraph.shared_data.deserializers

import com.my.dor_metagraph.shared_data.types.Types.{CheckInStateOnChain, CheckInUpdate}
import io.circe.{Decoder, parser}
import org.slf4j.LoggerFactory
import org.tessellation.currency.dataApplication.DataUpdate
import org.tessellation.currency.dataApplication.dataApplication.DataApplicationBlock
import org.tessellation.security.signature.Signed

import java.nio.charset.StandardCharsets

object Deserializers {
private val logger = LoggerFactory.getLogger("Deserializers")

def deserializeUpdate(bytes: Array[Byte]): Either[Throwable, CheckInUpdate] = {
parser.parse(new String(bytes, StandardCharsets.UTF_8)).flatMap { json =>
logger.info(json.toString())
json.as[CheckInUpdate]
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,23 +12,19 @@ import java.nio.charset.StandardCharsets
object Serializers {
private val logger = LoggerFactory.getLogger("Serializers")
def serializeUpdate(update: CheckInUpdate): Array[Byte] = {
logger.info("Serialize UPDATE event received")
logger.info(update.dtmCheckInHash)
logger.info(s"Serialize UPDATE event received ${update.dtmCheckInHash}")
update.dtmCheckInHash.getBytes(StandardCharsets.UTF_8)
}

def serializeState(state: CheckInStateOnChain): Array[Byte] = {
logger.info("Serialize STATE event received")
val jsonState = state.asJson.deepDropNullValues.noSpaces

logger.info(jsonState)
logger.info(s"Serialize STATE event received: $jsonState")
jsonState.getBytes(StandardCharsets.UTF_8)
}

def serializeBlock(state: Signed[DataApplicationBlock])(implicit e: Encoder[DataUpdate]): Array[Byte] = {
logger.info("Serialize BLOCK event received")
val jsonState = state.asJson.deepDropNullValues.noSpaces
logger.info(jsonState)
logger.info(s"Serialize BLOCK event received: $jsonState")
state.asJson.deepDropNullValues.noSpaces.getBytes(StandardCharsets.UTF_8)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,24 @@ import cats.effect.unsafe.implicits.global
import cats.implicits.catsSyntaxApply
import com.my.dor_metagraph.shared_data.validations.TypeValidators.{validateCheckInLimitTimestamp, validateCheckInTimestampIsGreaterThanLastCheckIn, validateIfDeviceIsRegisteredOnDORApi}
import com.my.dor_metagraph.shared_data.types.Types.{CheckInDataCalculatedState, CheckInUpdate}
import org.slf4j.LoggerFactory
import org.tessellation.currency.dataApplication.dataApplication.DataApplicationValidationErrorOr
import org.tessellation.security.SecurityProvider
import org.tessellation.security.signature.signature.SignatureProof

object Validations {
private val logger = LoggerFactory.getLogger("Validations")
def deviceCheckInValidationsL0(checkInUpdate: CheckInUpdate, proofs: NonEmptySet[SignatureProof], state: CheckInDataCalculatedState)(implicit sp: SecurityProvider[IO]): IO[DataApplicationValidationErrorOr[Unit]] = {
val address = proofs.map(_.id).head.toAddress[IO].unsafeRunSync()
val validateCurrentCheckInGreaterThanLast = validateCheckInTimestampIsGreaterThanLastCheckIn(state, checkInUpdate, address)
val validateCheckInLimit = validateCheckInLimitTimestamp(checkInUpdate)
val validateIfDeviceDORApi = validateIfDeviceIsRegisteredOnDORApi(checkInUpdate)

logger.info(s"[L0 Validation] Received Update: $checkInUpdate")
logger.info(s"[L0 Validation] validateCurrentCheckInGreaterThanLast: ${validateCurrentCheckInGreaterThanLast.isValid}")
logger.info(s"[L0 Validation] validateCheckInLimit: ${validateCheckInLimit.isValid}")
logger.info(s"[L0 Validation] validateIfDeviceDORApi: ${validateIfDeviceDORApi.isValid}")

IO {
validateCurrentCheckInGreaterThanLast.productR(validateCheckInLimit).productR(validateIfDeviceDORApi)
}
Expand All @@ -25,6 +32,11 @@ object Validations {
def deviceCheckInValidationsL1(checkInUpdate: CheckInUpdate): IO[DataApplicationValidationErrorOr[Unit]] = {
val validateCheckInLimit = validateCheckInLimitTimestamp(checkInUpdate)
val validateIfDeviceDORApi = validateIfDeviceIsRegisteredOnDORApi(checkInUpdate)

logger.info(s"[L1 Validation] Received Update: $checkInUpdate")
logger.info(s"[L1 Validation] validateCheckInLimit: ${validateCheckInLimit.isValid}")
logger.info(s"[L1 Validation] validateIfDeviceDORApi: ${validateIfDeviceDORApi.isValid}")

IO {
validateCheckInLimit.productR(validateIfDeviceDORApi)
}
Expand Down

0 comments on commit 70674cd

Please sign in to comment.