Skip to content

Commit

Permalink
NODE-2595 Change block reward distribution (#3853)
Browse files Browse the repository at this point in the history
  • Loading branch information
ivan-mashonskiy authored Jun 7, 2023
1 parent a062faa commit 24ee0e7
Show file tree
Hide file tree
Showing 34 changed files with 1,724 additions and 266 deletions.
4 changes: 4 additions & 0 deletions docker/private/waves.custom.conf
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ waves {
15 = 0
16 = 0
17 = 0
18 = 0
19 = 0
20 = 0
}
double-features-periods-after-height = 1000000000
max-transaction-time-back-offset = 120m
Expand All @@ -59,6 +62,7 @@ waves {
}
rewards {
term = 6
term-after-capped-reward-feature = 3
initial = 600000000
min-increment = 50000000
voting-interval = 3
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,10 +76,16 @@ object BlocksApiGrpcImpl {
BlockWithHeight(
Some(PBBlock(Some(blockMeta.header.toPBHeader), blockMeta.signature.toByteString, txs.map(_._2.toPB))),
blockMeta.height,
blockMeta.vrf.fold(ByteString.EMPTY)(_.toByteString)
blockMeta.vrf.fold(ByteString.EMPTY)(_.toByteString),
blockMeta.rewardShares.map { case (addr, reward) => RewardShare(ByteString.copyFrom(addr.bytes), reward) }
)
}

private def toBlockWithHeight(m: BlockMeta) =
BlockWithHeight(Some(PBBlock(Some(m.header.toPBHeader), m.signature.toByteString)), m.height, m.vrf.fold(ByteString.EMPTY)(_.toByteString))
BlockWithHeight(
Some(PBBlock(Some(m.header.toPBHeader), m.signature.toByteString)),
m.height,
m.vrf.fold(ByteString.EMPTY)(_.toByteString),
m.rewardShares.map { case (addr, reward) => RewardShare(ByteString.copyFrom(addr.bytes), reward) }
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -95,18 +95,18 @@ class BlockchainUpdates(private val context: Context) extends Extension with Sco
override def onProcessBlock(
block: Block,
diff: BlockDiffer.DetailedDiff,
minerReward: Option[Long],
reward: Option[Long],
hitSource: ByteStr,
blockchainBeforeWithMinerReward: Blockchain
): Unit = repo.onProcessBlock(block, diff, minerReward, hitSource, blockchainBeforeWithMinerReward)
blockchainBeforeWithReward: Blockchain
): Unit = repo.onProcessBlock(block, diff, reward, hitSource, blockchainBeforeWithReward)

override def onProcessMicroBlock(
microBlock: MicroBlock,
diff: BlockDiffer.DetailedDiff,
blockchainBeforeWithMinerReward: Blockchain,
blockchainBeforeWithReward: Blockchain,
totalBlockId: ByteStr,
totalTransactionsRoot: ByteStr
): Unit = repo.onProcessMicroBlock(microBlock, diff, blockchainBeforeWithMinerReward, totalBlockId, totalTransactionsRoot)
): Unit = repo.onProcessMicroBlock(microBlock, diff, blockchainBeforeWithReward, totalBlockId, totalTransactionsRoot)

override def onRollback(blockchainBefore: Blockchain, toBlockId: ByteStr, toHeight: Int): Unit =
repo.onRollback(blockchainBefore, toBlockId, toHeight)
Expand Down
10 changes: 5 additions & 5 deletions grpc-server/src/main/scala/com/wavesplatform/events/Repo.scala
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,9 @@ class Repo(db: DB, blocksApi: CommonBlocksApi)(implicit s: Scheduler) extends Bl
override def onProcessBlock(
block: Block,
diff: BlockDiffer.DetailedDiff,
minerReward: Option[Long],
reward: Option[Long],
hitSource: ByteStr,
blockchainBeforeWithMinerReward: Blockchain
blockchainBeforeWithReward: Blockchain
): Unit = monitor.synchronized {
require(
liquidState.forall(_.totalBlockId == block.header.reference),
Expand All @@ -74,15 +74,15 @@ class Repo(db: DB, blocksApi: CommonBlocksApi)(implicit s: Scheduler) extends Bl
db.put(keyForHeight(ls.keyBlock.height), ls.solidify().protobuf.update(_.append.block.optionalBlock := None).toByteArray)
)

val ba = BlockAppended.from(block, diff, blockchainBeforeWithMinerReward, minerReward, hitSource)
val ba = BlockAppended.from(block, diff, blockchainBeforeWithReward, reward, hitSource)
liquidState = Some(LiquidState(ba, Seq.empty))
handlers.forEach(_.handleUpdate(ba))
}

override def onProcessMicroBlock(
microBlock: MicroBlock,
diff: BlockDiffer.DetailedDiff,
blockchainBeforeWithMinerReward: Blockchain,
blockchainBeforeWithReward: Blockchain,
totalBlockId: ByteStr,
totalTransactionsRoot: ByteStr
): Unit = monitor.synchronized {
Expand All @@ -92,7 +92,7 @@ class Repo(db: DB, blocksApi: CommonBlocksApi)(implicit s: Scheduler) extends Bl
s"Microblock reference ${microBlock.reference} does not match last block id ${liquidState.get.totalBlockId}"
)

val mba = MicroBlockAppended.from(microBlock, diff, blockchainBeforeWithMinerReward, totalBlockId, totalTransactionsRoot)
val mba = MicroBlockAppended.from(microBlock, diff, blockchainBeforeWithReward, totalBlockId, totalTransactionsRoot)
liquidState = Some(ls.copy(microBlocks = ls.microBlocks :+ mba))

handlers.forEach(_.handleUpdate(mba))
Expand Down
40 changes: 23 additions & 17 deletions grpc-server/src/main/scala/com/wavesplatform/events/events.scala
Original file line number Diff line number Diff line change
Expand Up @@ -529,32 +529,33 @@ object StateUpdate {
.flatMap(id => blockchain.assetDescription(IssuedAsset(id)).map(ad => AssetInfo(id, ad.decimals, ad.name.toStringUtf8)))

def container(
blockchainBeforeWithMinerReward: Blockchain,
blockchainBeforeWithReward: Blockchain,
diff: DetailedDiff,
minerAddress: Address
): (StateUpdate, Seq[StateUpdate], Seq[TransactionMetadata], Seq[AssetInfo]) = {
val DetailedDiff(parentDiff, txsDiffs) = diff
val parentStateUpdate = atomic(blockchainBeforeWithMinerReward, parentDiff)
val parentStateUpdate = atomic(blockchainBeforeWithReward, parentDiff)

// miner reward is already in the blockchainBeforeWithMinerReward
// miner reward is already in the blockchainBeforeWithReward
// if miner balance has been changed in parentDiff, it is already included in balance updates
// if it has not, it needs to be manually requested from the blockchain and added to balance updates
// TODO: remove
val parentStateUpdateWithMinerReward = parentStateUpdate.balances.find(_.address == minerAddress) match {
case Some(_) => parentStateUpdate
case None =>
val minerBalance = blockchainBeforeWithMinerReward.balance(minerAddress, Waves)
val reward = blockchainBeforeWithMinerReward.blockReward(blockchainBeforeWithMinerReward.height).getOrElse(0L)
val minerBalance = blockchainBeforeWithReward.balance(minerAddress, Waves)
val reward = blockchainBeforeWithReward.blockReward(blockchainBeforeWithReward.height).getOrElse(0L)
parentStateUpdate.copy(balances = parentStateUpdate.balances :+ BalanceUpdate(minerAddress, Waves, minerBalance - reward, minerBalance))
}

val (txsStateUpdates, totalDiff) = txsDiffs.reverse
.foldLeft((Seq.empty[StateUpdate], parentDiff)) { case ((updates, accDiff), txDiff) =>
(
updates :+ atomic(CompositeBlockchain(blockchainBeforeWithMinerReward, accDiff), txDiff),
updates :+ atomic(CompositeBlockchain(blockchainBeforeWithReward, accDiff), txDiff),
accDiff.combineF(txDiff).explicitGet()
)
}
val blockchainAfter = CompositeBlockchain(blockchainBeforeWithMinerReward, totalDiff)
val blockchainAfter = CompositeBlockchain(blockchainBeforeWithReward, totalDiff)
val metadata = transactionsMetadata(blockchainAfter, totalDiff)
val refAssets = referencedAssets(blockchainAfter, txsStateUpdates)
(parentStateUpdateWithMinerReward, txsStateUpdates, metadata, refAssets)
Expand Down Expand Up @@ -593,6 +594,7 @@ final case class BlockAppended(
updatedWavesAmount: Long,
vrf: Option[ByteStr],
activatedFeatures: Seq[Int],
rewardShares: Seq[(Address, Long)],
blockStateUpdate: StateUpdate,
transactionStateUpdates: Seq[StateUpdate],
transactionMetadata: Seq[TransactionMetadata],
Expand All @@ -608,29 +610,33 @@ object BlockAppended {
def from(
block: Block,
diff: DetailedDiff,
blockchainBeforeWithMinerReward: Blockchain,
minerReward: Option[Long],
blockchainBeforeWithReward: Blockchain,
reward: Option[Long],
hitSource: ByteStr
): BlockAppended = {
val height = blockchainBeforeWithMinerReward.height
val height = blockchainBeforeWithReward.height
val (blockStateUpdate, txsStateUpdates, txsMetadata, refAssets) =
StateUpdate.container(blockchainBeforeWithMinerReward, diff, block.sender.toAddress)
StateUpdate.container(blockchainBeforeWithReward, diff, block.sender.toAddress)

// updatedWavesAmount can change as a result of either genesis transactions or miner rewards
val wavesAmount = blockchainBeforeWithMinerReward.wavesAmount(height).toLong
val updatedWavesAmount = wavesAmount + minerReward.filter(_ => height > 0).getOrElse(0L)
val wavesAmount = blockchainBeforeWithReward.wavesAmount(height).toLong
val updatedWavesAmount = wavesAmount + reward.filter(_ => height > 0).getOrElse(0L)

val activatedFeatures = blockchainBeforeWithMinerReward.activatedFeatures.collect {
val activatedFeatures = blockchainBeforeWithReward.activatedFeatures.collect {
case (id, activationHeight) if activationHeight == height + 1 => id.toInt
}.toSeq

val rewardShares =
BlockRewardCalculator.getSortedBlockRewardShares(height + 1, reward.getOrElse(0L), block.header.generator.toAddress, blockchainBeforeWithReward)

BlockAppended(
block.id(),
height + 1,
block,
updatedWavesAmount,
if (block.header.version >= Block.ProtoBlockVersion) Some(hitSource) else None,
activatedFeatures,
rewardShares,
blockStateUpdate,
txsStateUpdates,
txsMetadata,
Expand Down Expand Up @@ -662,16 +668,16 @@ object MicroBlockAppended {
def from(
microBlock: MicroBlock,
diff: DetailedDiff,
blockchainBeforeWithMinerReward: Blockchain,
blockchainBeforeWithReward: Blockchain,
totalBlockId: ByteStr,
totalTransactionsRoot: ByteStr
): MicroBlockAppended = {
val (microBlockStateUpdate, txsStateUpdates, txsMetadata, refAssets) =
StateUpdate.container(blockchainBeforeWithMinerReward, diff, microBlock.sender.toAddress)
StateUpdate.container(blockchainBeforeWithReward, diff, microBlock.sender.toAddress)

MicroBlockAppended(
totalBlockId,
blockchainBeforeWithMinerReward.height,
blockchainBeforeWithReward.height,
microBlock,
microBlockStateUpdate,
txsStateUpdates,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package com.wavesplatform.events.protobuf

import cats.Monoid
import com.google.protobuf.ByteString
import com.wavesplatform.account.Address
import com.wavesplatform.common.utils.EitherExt2
import com.wavesplatform.events.StateUpdate.AssetInfo
import com.wavesplatform.events.protobuf.BlockchainUpdated.Append.Body
import com.wavesplatform.events.protobuf.BlockchainUpdated.{Append, Rollback, Update}
Expand All @@ -27,6 +29,7 @@ package object serde {
updatedWavesAmount,
vrf,
activatedFeatures,
rewardShares,
blockStateUpdate,
transactionStateUpdates,
transactionsMetadata,
Expand All @@ -49,7 +52,8 @@ package object serde {
block = Some(PBBlocks.protobuf(block)),
updatedWavesAmount = updatedWavesAmount,
activatedFeatures = activatedFeatures,
vrf = vrf.fold(ByteString.EMPTY)(_.toByteString)
vrf = vrf.fold(ByteString.EMPTY)(_.toByteString),
rewardShares = rewardShares.map { case (addr, reward) => RewardShare(ByteString.copyFrom(addr.bytes), reward) }
)
)
)
Expand Down Expand Up @@ -138,6 +142,7 @@ package object serde {
updatedWavesAmount = body.updatedWavesAmount,
vrf = Option.unless(body.vrf.isEmpty)(body.vrf.toByteStr),
activatedFeatures = body.activatedFeatures,
rewardShares = body.rewardShares.map { rs => (Address.fromBytes(rs.address.toByteArray).explicitGet(), rs.reward) },
blockStateUpdate = append.stateUpdate.fold(Monoid[ve.StateUpdate].empty)(_.vanilla.get),
transactionStateUpdates = append.transactionStateUpdates.map(_.vanilla.get),
transactionMetadata = append.transactionsMetadata,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ object LiquidState {
updatedWavesAmount = keyBlock.updatedWavesAmount,
vrf = keyBlock.vrf,
activatedFeatures = keyBlock.activatedFeatures,
rewardShares = keyBlock.rewardShares,
blockStateUpdate = blockStateUpdate,
transactionStateUpdates = transactionStateUpdates,
transactionMetadata = transactionMetadata,
Expand Down
Loading

0 comments on commit 24ee0e7

Please sign in to comment.