From 58667d8fd2491bb2b0b47a4c8574331fa99678c4 Mon Sep 17 00:00:00 2001 From: Vyatcheslav Suharnikov Date: Mon, 16 Sep 2024 17:05:40 +0400 Subject: [PATCH] chain contract: do not store a generator a the block metadata --- local-network/deploy/common-settings-show.ts | 9 ++++ src/main/scala/units/ELUpdater.scala | 4 +- .../client/contract/ChainContractClient.scala | 31 ++++-------- .../units/client/contract/ContractBlock.scala | 4 +- src/test/resources/main.ride | 47 +++++++++---------- 5 files changed, 44 insertions(+), 51 deletions(-) diff --git a/local-network/deploy/common-settings-show.ts b/local-network/deploy/common-settings-show.ts index 12307328..ebce6835 100644 --- a/local-network/deploy/common-settings-show.ts +++ b/local-network/deploy/common-settings-show.ts @@ -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}`); + diff --git a/src/main/scala/units/ELUpdater.scala b/src/main/scala/units/ELUpdater.scala index 48e64ad6..6e35a968 100644 --- a/src/main/scala/units/ELUpdater.scala +++ b/src/main/scala/units/ELUpdater.scala @@ -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) } @@ -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 { diff --git a/src/main/scala/units/client/contract/ChainContractClient.scala b/src/main/scala/units/client/contract/ChainContractClient.scala index 93d9007e..fdb8889a 100644 --- a/src/main/scala/units/client/contract/ChainContractClient.scala +++ b/src/main/scala/units/client/contract/ChainContractClient.scala @@ -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 @@ -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")) @@ -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 = @@ -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, @@ -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 { @@ -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 diff --git a/src/main/scala/units/client/contract/ContractBlock.scala b/src/main/scala/units/client/contract/ContractBlock.scala index a1ea7858..a748aafa 100644 --- a/src/main/scala/units/client/contract/ContractBlock.scala +++ b/src/main/scala/units/client/contract/ContractBlock.scala @@ -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 @@ -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)" } diff --git a/src/test/resources/main.ride b/src/test/resources/main.ride index dc6efa6b..4ea2a51d 100644 --- a/src/test/resources/main.ride +++ b/src/test/resources/main.ride @@ -129,27 +129,26 @@ 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() @@ -157,7 +156,7 @@ func mkBlockMetaEntry( 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) @@ -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("") @@ -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) @@ -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), @@ -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 @@ -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), @@ -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 @@ -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), @@ -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) @@ -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) @@ -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 @@ -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) @@ -676,7 +676,6 @@ func setup(genesisBlockHashHex: String, minerRewardInGwei: Int) = { genesisBlockHashHex, 0, # blockHeight genesisBlockReferenceHash, - genesisMinerAddress, 0, # chainId base16''.toBase16String(), # elToClTransfersRootHashHex -1 # lastClToElTransferIndex