Skip to content

Commit

Permalink
chain contract: do not store a generator a the block metadata
Browse files Browse the repository at this point in the history
  • Loading branch information
vsuharnikov committed Sep 16, 2024
1 parent 04c7c7f commit 58667d8
Show file tree
Hide file tree
Showing 5 changed files with 44 additions and 51 deletions.
9 changes: 9 additions & 0 deletions local-network/deploy/common-settings-show.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,11 @@
import * as all from "./src/common-settings";
import * as n from "./src/nodes";

console.log(all);

const elBridgeAddressResponse = await n.wavesApi1.addresses.fetchDataKey(all.chainContract.address, 'elBridgeAddress');
if (!elBridgeAddressResponse.value || elBridgeAddressResponse.type != 'string') throw new Error(`Unexpected value of "tokenId" contract key in response: ${elBridgeAddressResponse}`);
const elBridgeAddress = elBridgeAddressResponse.value;

console.log(`EL bridge address from contract: ${elBridgeAddress}`);

4 changes: 2 additions & 2 deletions src/main/scala/units/ELUpdater.scala
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ class ELUpdater(
header <- blockchain.blockHeader(epochNumber).toRight(s"No header at epoch $epochNumber")
hitSource <- blockchain.hitSource(epochNumber).toRight(s"No hit source at epoch $epochNumber")
miner <- chainContractClient.calculateEpochMiner(header.header, hitSource, epochNumber, blockchain)
rewardAddress <- chainContractClient.getL2RewardAddress(miner).toRight(s"No reward address for $miner")
rewardAddress <- chainContractClient.getElRewardAddress(miner).toRight(s"No reward address for $miner")
prevEpochLastBlockHash <- getPrevEpochLastBlockHash(epochNumber)
} yield EpochInfo(epochNumber, miner, rewardAddress, hitSource, prevEpochLastBlockHash)
}
Expand Down Expand Up @@ -1304,7 +1304,7 @@ class ELUpdater(

val isEpochFirstBlock = contractBlock.parentHash == blockPrevEpoch.lastBlockHash
val expectMiningReward = isEpochFirstBlock && !contractBlock.referencesGenesis
val prevMinerElRewardAddress = if (expectMiningReward) chainContractClient.getL2RewardAddress(blockPrevEpoch.miner) else None
val prevMinerElRewardAddress = if (expectMiningReward) chainContractClient.getElRewardAddress(blockPrevEpoch.miner) else None

for {
elWithdrawalIndexBefore <- fullValidationStatus.checkedLastElWithdrawalIndex(ecBlock.parentHash) match {
Expand Down
31 changes: 9 additions & 22 deletions src/main/scala/units/client/contract/ChainContractClient.scala
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import units.BlockHash
import units.client.contract.ChainContractClient.*
import units.eth.{EthAddress, Gwei}
import units.util.HexBytesConverter
import units.util.HexBytesConverter.*

import java.nio.ByteBuffer
import scala.reflect.ClassTag
Expand Down Expand Up @@ -46,7 +45,7 @@ trait ChainContractClient {
.flatMap(_.split(Sep))
.flatMap(Address.fromString(_).toOption)

def getL2RewardAddress(miner: Address): Option[EthAddress] = getElRewardAddress(ByteStr(miner.bytes))
def getElRewardAddress(miner: Address): Option[EthAddress] = getElRewardAddress(ByteStr(miner.bytes))
private def getElRewardAddress(minerAddress: ByteStr): Option[EthAddress] =
extractData(s"miner_${minerAddress}_RewardAddress")
.orElse(extractData(s"miner${minerAddress}RewardAddress"))
Expand All @@ -62,7 +61,6 @@ trait ChainContractClient {
val chainHeight = bb.getLong()
val epoch = bb.getLong().toInt // blockMeta is set up in a chain contract and RIDE numbers are Longs
val parentHash = BlockHash(bb.getByteArray(BlockHashBytesSize))
val clGenerator = ByteStr(bb.getByteArray(Address.AddressLength))
val chainId = if (bb.remaining() >= 8) bb.getLong() else 0L

val e2CTransfersRootHash =
Expand All @@ -74,20 +72,21 @@ trait ChainContractClient {
require(
!bb.hasRemaining,
s"Not parsed ${bb.remaining()} bytes from ${blockMeta.base64}, read data: " +
s"chainHeight=$chainHeight, epoch=$epoch, parentHash=$parentHash, clGenerator=$clGenerator, chainId=$chainId, " +
s"chainHeight=$chainHeight, epoch=$epoch, parentHash=$parentHash, chainId=$chainId, " +
s"e2CTransfersRootHash=${HexBytesConverter.toHex(e2CTransfersRootHash)}, lastC2ETransferIndex=$lastC2ETransferIndex"
)

val epochMeta = getEpochMeta(epoch).getOrElse(fail(s"Can't find epoch meta for epoch $epoch"))

val minerRewardElAddress =
if (chainHeight == 0) EthAddress.empty
else getElRewardAddress(clGenerator).getOrElse(fail(s"Can't find a reward address for generator $clGenerator"))
else getElRewardAddress(epochMeta.miner).getOrElse(fail(s"Can't find a reward address for generator ${epochMeta.miner}"))

ContractBlock(
hash,
parentHash,
epoch,
chainHeight,
clGenerator,
minerRewardElAddress,
chainId,
e2CTransfersRootHash,
Expand All @@ -104,23 +103,12 @@ trait ChainContractClient {
def getFirstValidAltChainId: Long =
getLongData("firstValidAltChainId").getOrElse(DefaultMainChainId)

def getStakingContractAddress: Option[Address] =
extractData(StakingContractAddressKey)
.collect {
case StringDataEntry(_, v) => Address.fromString(v)
case BinaryDataEntry(_, bs) => Address.fromBytes(bs.arr)
}
.flatMap(_.toOption)

def getMainChainIdOpt: Option[Long] =
getLongData(MainChainIdKey)

def getMainChainId: Long =
getMainChainIdOpt.getOrElse(DefaultMainChainId)

def getGeneratorChainId(generator: ByteStr): Long =
getLongData(s"chainIdOf${toHex(generator)}").getOrElse(DefaultMainChainId)

def getEpochMeta(epoch: Int): Option[EpochContractMeta] = getStringData(f"epoch_$epoch%08d").flatMap { s =>
val items = s.split(Sep)
if (items.length == 3) for {
Expand Down Expand Up @@ -277,11 +265,10 @@ object ChainContractClient {
val MinMinerBalance: Long = 20000_00000000L
val DefaultMainChainId = 0

private val AllMinersKey = "allMiners"
private val MainChainIdKey = "mainChainId"
private val StakingContractAddressKey = "stakingContractAddress"
private val BlockHashBytesSize = 32
private val Sep = ","
private val AllMinersKey = "allMiners"
private val MainChainIdKey = "mainChainId"
private val BlockHashBytesSize = 32
private val Sep = ","

val MaxClToElTransfers = 16

Expand Down
4 changes: 1 addition & 3 deletions src/main/scala/units/client/contract/ContractBlock.scala
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package units.client.contract

import com.wavesplatform.common.merkle.Digest
import com.wavesplatform.common.state.ByteStr
import units.BlockHash
import units.client.L2BlockLike
import units.eth.EthAddress
Expand All @@ -12,14 +11,13 @@ case class ContractBlock(
parentHash: BlockHash,
epoch: Int,
height: Long,
generator: ByteStr,
minerRewardL2Address: EthAddress,
chainId: Long,
elToClTransfersRootHash: Digest,
lastClToElTransferIndex: Long
) extends L2BlockLike {
override def toString: String =
s"ContractBlock($hash, p=$parentHash, e=$epoch, h=$height, m=$minerRewardL2Address ($generator), c=$chainId, " +
s"ContractBlock($hash, p=$parentHash, e=$epoch, h=$height, m=$minerRewardL2Address, c=$chainId, " +
s"e2c=${if (elToClTransfersRootHash.isEmpty) "" else toHex(elToClTransfersRootHash)}, c2e=$lastClToElTransferIndex)"
}

Expand Down
47 changes: 23 additions & 24 deletions src/test/resources/main.ride
Original file line number Diff line number Diff line change
Expand Up @@ -129,35 +129,34 @@ func blockMeta(blockId: String) = {
let meta = getBinaryValue(blockMetaK + blockId)
let metaSize = meta.size()

let blockHeight = meta.toInt() # _1
let blockEpoch = meta.toInt(8) # _2
let blockParent = meta.drop(16).take(BLOCK_HASH_SIZE) # _3
let blockGenerator = meta.drop(16 + BLOCK_HASH_SIZE).take(ADDRESS_SIZE) # _4
let chainId = meta.toInt(16 + BLOCK_HASH_SIZE + ADDRESS_SIZE) # _5
let blockHeight = meta.toInt() # _1
let blockEpoch = meta.toInt(8) # _2
let blockParent = meta.drop(16).take(BLOCK_HASH_SIZE) # _3
let chainId = meta.toInt(16 + BLOCK_HASH_SIZE) # _4

let baseOffset = 24 + BLOCK_HASH_SIZE + ADDRESS_SIZE
let baseOffset = 24 + BLOCK_HASH_SIZE
let remainingBytes = metaSize - baseOffset
let elToClTransfersRootHash = if (remainingBytes >= ROOT_HASH_SIZE) # _6
let elToClTransfersRootHash = if (remainingBytes >= ROOT_HASH_SIZE) # _5
then meta.drop(baseOffset).take(ROOT_HASH_SIZE)
else base16''

let lastClToElTransferIndex = if (remainingBytes == 8 || remainingBytes > ROOT_HASH_SIZE) # _7
let lastClToElTransferIndex = if (remainingBytes == 8 || remainingBytes > ROOT_HASH_SIZE) # _6
then meta.toInt(baseOffset + elToClTransfersRootHash.size())
else -1

(blockHeight, blockEpoch, blockParent, blockGenerator, chainId, elToClTransfersRootHash, lastClToElTransferIndex)
(blockHeight, blockEpoch, blockParent, chainId, elToClTransfersRootHash, lastClToElTransferIndex)
}

func mkBlockMetaEntry(
blockHashHex: String, blockHeight: Int, blockParentHex: String, blockGenerator: Address, chainId: Int,
blockHashHex: String, blockHeight: Int, blockParentHex: String, chainId: Int,
elToClTransfersRootHashHex: String, lastClToElTransferIndex: Int
) = {
let elToClTransfersRootHashBytes = elToClTransfersRootHashHex.fromBase16String()
let rootHashBytesSize = elToClTransfersRootHashBytes.size()
strict checkRootHash = if (rootHashBytesSize == 0 || rootHashBytesSize == ROOT_HASH_SIZE) then true
else throw("Transfers root hash should have 0 or " + ROOT_HASH_SIZE.toString() + " bytes, got " + rootHashBytesSize.toString())

let blockMetaBytes = blockHeight.toBytes() + height.toBytes() + blockParentHex.fromBase16String() + blockGenerator.bytes +
let blockMetaBytes = blockHeight.toBytes() + height.toBytes() + blockParentHex.fromBase16String() +
chainId.toBytes() + elToClTransfersRootHashBytes + lastClToElTransferIndex.toBytes()

BinaryEntry(blockMetaK + blockHashHex, blockMetaBytes)
Expand Down Expand Up @@ -195,7 +194,8 @@ let (computedDelay, computedGenerator, computedTotalBalance, filteredMiners) = {

func getChainLastBlockId(chainId: Int) = chainMeta(chainId)._2

let (mclbIgnored1, mainChainEpoch, mainChainParentHash, mainChainGenerator) = blockMeta(mainChainLastBlock)
let (mclbIgnored1, mainChainEpoch, mainChainParentHash) = blockMeta(mainChainLastBlock)
let (mainChainGenerator, mceIgnored1) = epochMeta(mainChainEpoch).valueOrErrorMessage("Can't find main chain epoch meta for epoch " + mainChainEpoch.toString())

func calculateFinalizedBlockHash(curMiner: Address, curPrevEpoch: Int, curLastBlockHash: String) = {
let offsets_100 = "::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::".split_4C("")
Expand Down Expand Up @@ -349,7 +349,7 @@ func extendMainChain(
strict checkEpoch = ensureCorrectEpoch(vrf)
strict checkChain = ensureExpectedOrInactiveChain(i.originCaller, mainChainId, unit)
strict checkReference = isReferenceCorrect(referenceHex, mainChainLastBlock)
strict checkTransfers = ensureCorrectTransfers(blockMeta(referenceHex)._7, lastClToElTransferIndex, true)
strict checkTransfers = ensureCorrectTransfers(blockMeta(referenceHex)._6, lastClToElTransferIndex, true)

strict thisEpochMeta = match epochMeta(height) {
case _: Unit => StringEntry(epochMetaKey(height), i.originCaller.toString() + SEP + mainChainEpoch.toString() + SEP + blockHashHex)
Expand All @@ -362,7 +362,7 @@ func extendMainChain(

let newChainHeight = mainChainHeight + 1
[
mkBlockMetaEntry(blockHashHex, newChainHeight, mainChainLastBlock, i.originCaller, mainChainId, elToClTransfersRootHashHex, lastClToElTransferIndex),
mkBlockMetaEntry(blockHashHex, newChainHeight, mainChainLastBlock, mainChainId, elToClTransfersRootHashHex, lastClToElTransferIndex),
mkChainMetaEntry(mainChainId, newChainHeight, blockHashHex),
IntegerEntry(minerChainIdKey(i.originCaller), mainChainId),
IntegerEntry(chainLastHeightKey(mainChainId, i.originCaller), newChainHeight),
Expand All @@ -380,7 +380,7 @@ func startAltChain(
) = {
strict checkBlockHash = validateBlockHash(blockHashHex)
strict checkEpoch = ensureCorrectEpoch(vrf)
let (refChainHeight, refEpoch, refRef, refGenerator, refIgnored5, refIgnored6, refTransferIndex) = blockMeta(referenceHex)
let (refChainHeight, refEpoch, refRef, refIgnored5, refIgnored6, refTransferIndex) = blockMeta(referenceHex)
let finalizedEpoch = blockMeta(getStringValue(finalizedBlockKey))._2
let epochRef = if (refEpoch >= finalizedEpoch)
then refEpoch
Expand All @@ -400,7 +400,7 @@ func startAltChain(

[
thisEpochMeta,
mkBlockMetaEntry(blockHashHex, newChainHeight, referenceHex, i.originCaller, newChainId, elToClTransfersRootHashHex, lastClToElTransferIndex),
mkBlockMetaEntry(blockHashHex, newChainHeight, referenceHex, newChainId, elToClTransfersRootHashHex, lastClToElTransferIndex),
StringEntry(chainFirstBlockIdKey(newChainId), blockHashHex),
mkChainMetaEntry(newChainId, newChainHeight, blockHashHex),
IntegerEntry(minerChainIdKey(i.originCaller), newChainId),
Expand Down Expand Up @@ -431,7 +431,7 @@ func extendAltChain(
strict checkChain = ensureExpectedOrInactiveChain(i.originCaller, chainId, chainFirstBlockMeta._3.toBase16String())
let (chainHeight, chainLastBlock) = chainMeta(chainId)
strict checkReference = isReferenceCorrect(referenceHex, chainLastBlock)
strict checkTransfers = ensureCorrectTransfers(blockMeta(referenceHex)._7, lastClToElTransferIndex, true)
strict checkTransfers = ensureCorrectTransfers(blockMeta(referenceHex)._6, lastClToElTransferIndex, true)

let newChainHeight = chainHeight + 1

Expand Down Expand Up @@ -460,7 +460,7 @@ func extendAltChain(
[IntegerEntry(chainLastHeightKey(mainChainId, i.originCaller), chainFirstBlockMeta._1)]
} else []
[
mkBlockMetaEntry(blockHashHex, newChainHeight, referenceHex, i.originCaller, chainId, elToClTransfersRootHashHex, lastClToElTransferIndex),
mkBlockMetaEntry(blockHashHex, newChainHeight, referenceHex, chainId, elToClTransfersRootHashHex, lastClToElTransferIndex),
mkChainMetaEntry(chainId, newChainHeight, blockHashHex),
thisEpochMeta,
IntegerEntry(minerChainIdKey(i.originCaller), chainId),
Expand All @@ -486,12 +486,12 @@ func appendBlock(

let (chainHeight, lastBlockId) = chainMeta(chainId)
strict checkReference = isReferenceCorrect(referenceHex, lastBlockId)
strict checkTransfers = ensureCorrectTransfers(blockMeta(referenceHex)._7, lastClToElTransferIndex, false)
strict checkTransfers = ensureCorrectTransfers(blockMeta(referenceHex)._6, lastClToElTransferIndex, false)

let newChainHeight = chainHeight + 1
strict checkBlockHash = validateBlockHash(blockHashHex)
[
mkBlockMetaEntry(blockHashHex, newChainHeight, lastBlockId, i.originCaller, chainId, elToClTransfersRootHashHex, lastClToElTransferIndex),
mkBlockMetaEntry(blockHashHex, newChainHeight, lastBlockId, chainId, elToClTransfersRootHashHex, lastClToElTransferIndex),
IntegerEntry(chainLastHeightKey(chainId, i.originCaller), newChainHeight),
mkChainMetaEntry(chainId, newChainHeight, blockHashHex),
StringEntry(epochMetaKey(height), thisEpochMiner.value().toString() + SEP + thisEpochRef.toString() + SEP + blockHashHex)
Expand Down Expand Up @@ -588,7 +588,7 @@ func transfer(destElAddressHex: String) = {
case _ => throw("Expected " + tokenIdStr + " in the payment, got Waves")
}

let lastIndex = blockMeta(mainChainLastBlock)._7
let lastIndex = blockMeta(mainChainLastBlock)._6
let queueSize = nativeTransfersCount - lastIndex
strict checkQueueLimit =
if (queueSize < 160) then amountGtEq(t, 1_000_000, queueSize)
Expand Down Expand Up @@ -616,7 +616,7 @@ func withdraw(blockHashHex: String, merkleProof: List[ByteVector], transferIndex
else if (transferIndexInBlock < 0) then throw("Transfer index in block should be nonnegative, got " + transferIndexInBlock.toString())
else if (amount <= 0) then throw("Amount should be positive, got " + amount.toString())
else {
let withdrawBlockChainId = withdrawBlockMeta._5
let withdrawBlockChainId = withdrawBlockMeta._4
let isMainChain = withdrawBlockChainId == mainChainId

# A chain forked after a block with withdrawal
Expand All @@ -636,7 +636,7 @@ func withdraw(blockHashHex: String, merkleProof: List[ByteVector], transferIndex
let elEventDataDigest = blake2b256_16Kb(elEventData)

let calculatedRootHash = createMerkleRoot(merkleProof, elEventDataDigest, transferIndexInBlock)
let expectedRootHash = withdrawBlockMeta._6
let expectedRootHash = withdrawBlockMeta._5
if (calculatedRootHash == expectedRootHash) then {
let tokenId = getStringValue(tokenIdKey).fromBase58String()
let transfersKey = blockElToClTransfersKey(blockHashHex)
Expand Down Expand Up @@ -676,7 +676,6 @@ func setup(genesisBlockHashHex: String, minerRewardInGwei: Int) = {
genesisBlockHashHex,
0, # blockHeight
genesisBlockReferenceHash,
genesisMinerAddress,
0, # chainId
base16''.toBase16String(), # elToClTransfersRootHashHex
-1 # lastClToElTransferIndex
Expand Down

0 comments on commit 58667d8

Please sign in to comment.