From 6f265f0effca51b9f01efe22dac2f60780bb85fb Mon Sep 17 00:00:00 2001 From: Vyatcheslav Suharnikov Date: Wed, 20 Nov 2024 19:02:50 +0400 Subject: [PATCH 1/9] Support a chain registry: - Consensus Client works only if it is approved on a chain registry; - Approvals and rejections are detected during work; - Migrated settings from ficus to pureconfig; - New tests. --- build.sbt | 18 +++-- .../src/test/scala/units/Accounts.scala | 1 + .../scala/units/BaseDockerTestSuite.scala | 3 + .../scala/units/RegistryDockerTestSuite.scala | 30 +++++++++ docker/Dockerfile | 2 +- .../configs/wavesnode/genesis-template.conf | 9 +++ local-network/configs/wavesnode/waves.conf | 3 + local-network/deploy/deploy.py | 6 ++ local-network/deploy/local/network.py | 6 +- src/main/scala/units/ClientConfig.scala | 7 -- src/main/scala/units/ConsensusClient.scala | 13 +++- src/main/scala/units/ELUpdater.scala | 57 +++++++++------- .../scala/units/client/JsonRpcClient.scala | 7 +- .../units/BaseIntegrationTestSuite.scala | 12 +++- .../units/BlockBriefValidationTestSuite.scala | 2 +- .../units/BlockFullValidationTestSuite.scala | 2 +- .../units/BlockIssuesForgingTestSuite.scala | 4 +- .../scala/units/C2ETransfersTestSuite.scala | 2 +- .../scala/units/E2CTransfersTestSuite.scala | 4 +- src/test/scala/units/ExtensionDomain.scala | 6 +- src/test/scala/units/RegistryTestSuite.scala | 67 +++++++++++++++++++ src/test/scala/units/TestSettings.scala | 20 ++++-- .../scala/units/client/TestEcClients.scala | 7 +- .../HasConsensusLayerDappTxHelpers.scala | 22 +++++- 24 files changed, 242 insertions(+), 68 deletions(-) create mode 100644 consensus-client-it/src/test/scala/units/RegistryDockerTestSuite.scala create mode 100644 src/test/scala/units/RegistryTestSuite.scala diff --git a/build.sbt b/build.sbt index 1060985f..11bf8ecf 100644 --- a/build.sbt +++ b/build.sbt @@ -30,13 +30,17 @@ inScope(Global)( name := "consensus-client" maintainer := "Units Network Team" -libraryDependencies ++= Seq( - "com.wavesplatform" % "node-testkit" % "1.5.8" % Test, - "com.wavesplatform" % "node" % "1.5.8" % Provided, - "com.softwaremill.sttp.client3" % "core_2.13" % "3.10.1", - "com.softwaremill.sttp.client3" %% "play-json" % "3.10.1", - "com.github.jwt-scala" %% "jwt-play-json" % "10.0.1" -) +libraryDependencies ++= { + val node = "1.5-3977-SNAPSHOT" + val sttp = "3.10.1" + Seq( + "com.wavesplatform" % "node-testkit" % node % Test, + "com.wavesplatform" % "node" % node % Provided, + "com.softwaremill.sttp.client3" % "core_2.13" % sttp, + "com.softwaremill.sttp.client3" %% "play-json" % sttp, + "com.github.jwt-scala" %% "jwt-play-json" % "10.0.1" + ) +} Compile / packageDoc / publishArtifact := false diff --git a/consensus-client-it/src/test/scala/units/Accounts.scala b/consensus-client-it/src/test/scala/units/Accounts.scala index 227e60d0..8abdc383 100644 --- a/consensus-client-it/src/test/scala/units/Accounts.scala +++ b/consensus-client-it/src/test/scala/units/Accounts.scala @@ -9,6 +9,7 @@ import units.eth.EthAddress import java.nio.charset.StandardCharsets trait Accounts { + val chainRegistryAccount: KeyPair = mkKeyPair("devnet registry", 0) val chainContractAccount: KeyPair = mkKeyPair("devnet cc", 0) val miner11Account = mkKeyPair("devnet-1", 0) diff --git a/consensus-client-it/src/test/scala/units/BaseDockerTestSuite.scala b/consensus-client-it/src/test/scala/units/BaseDockerTestSuite.scala index 2cce8fb5..cc857c46 100644 --- a/consensus-client-it/src/test/scala/units/BaseDockerTestSuite.scala +++ b/consensus-client-it/src/test/scala/units/BaseDockerTestSuite.scala @@ -78,6 +78,9 @@ trait BaseDockerTestSuite } protected def setupChain(): Unit = { + log.info("Approve chain on registry") + waves1.api.broadcast(ChainRegistry.approve()) + log.info("Set script") waves1.api.broadcastAndWait(ChainContract.setScript()) diff --git a/consensus-client-it/src/test/scala/units/RegistryDockerTestSuite.scala b/consensus-client-it/src/test/scala/units/RegistryDockerTestSuite.scala new file mode 100644 index 00000000..81d709ad --- /dev/null +++ b/consensus-client-it/src/test/scala/units/RegistryDockerTestSuite.scala @@ -0,0 +1,30 @@ +package units + +class RegistryDockerTestSuite extends BaseDockerTestSuite { + "Approved, rejected, approved - mining works when approved" in { + step(s"Wait miner 1 (${miner11Account.toAddress}) forge at least one block") + chainContract.waitForHeight(1L) + + step("Broadcast a reject transaction") + val rejectTxnHeight = waves1.api.broadcastAndWait(ChainRegistry.reject()).height + + step("Wait a rejection height") + waves1.api.waitForHeight(rejectTxnHeight + 1) + val lastElBlock1 = chainContract.getLastBlockMeta(0L).value + + step("Expect no mining") + waves1.api.waitForHeight(rejectTxnHeight + 2) + + val lastElBlock2 = chainContract.getLastBlockMeta(0L).value + withClue("Same block - no mining: ") { + lastElBlock2.hash shouldBe lastElBlock1.hash + } + + val approveTxnHeight = waves1.api.broadcastAndWait(ChainRegistry.approve()).height + step("Wait an approval height") + waves1.api.waitForHeight(approveTxnHeight + 1) + + step("Mining working") + chainContract.waitForHeight(lastElBlock2.height + 1) + } +} diff --git a/docker/Dockerfile b/docker/Dockerfile index 8d6d3938..b1c29f21 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -1,4 +1,4 @@ -ARG baseImage=ghcr.io/wavesplatform/waves:1.5.8-1 +ARG baseImage=ghcr.io/wavesplatform/waves:units-registry FROM $baseImage COPY target /tmp/ RUN tar zxvf /tmp/consensus-client.tgz -C $WAVES_INSTALL_PATH --strip-components=1 diff --git a/local-network/configs/wavesnode/genesis-template.conf b/local-network/configs/wavesnode/genesis-template.conf index 99724a5c..91aaa3ce 100644 --- a/local-network/configs/wavesnode/genesis-template.conf +++ b/local-network/configs/wavesnode/genesis-template.conf @@ -62,6 +62,15 @@ genesis-generator { # Address: 3FVp6fUSmVehs7Q3uJBXe5kWtpz57f7azzA { seed-text = "devnet dao", nonce = 0, amount = 100000000 } + # Chain registry + # Seed text: devnet registry + # Nonce: 0 + # Seed: 3oujRTe9jVvnMHcKe9vGG + # Private key: 3kqzGQiNy5qTKEGDzCxh6Kk8LLXW5Lh22pLmZvFNqDm1 + # Public key: HRHrDistEQkJJ7dBxBBzxfSsbN8oEF8xt3FeUHLNBYfX + # Address: 3FibjK5ZAXFfJf9J3gDsheia88Vz2itLPu1 + { seed-text = "devnet registry", nonce = 0, amount = 100000000 } + # Chain contract # Seed text: devnet cc # Nonce: 0 diff --git a/local-network/configs/wavesnode/waves.conf b/local-network/configs/wavesnode/waves.conf index 4acda82f..663b5e1e 100644 --- a/local-network/configs/wavesnode/waves.conf +++ b/local-network/configs/wavesnode/waves.conf @@ -41,7 +41,9 @@ waves { dao-address = "3FVGizGxjdi8m4e8WKjbwtzg4rdiiUGkLCu" xtn-buyback-address = "3FZQMZsyypqDUk2r5katP1AUChe7Uzc9dC4" xtn-buyback-reward-period = 20 + units-registry-address = "3FibjK5ZAXFfJf9J3gDsheia88Vz2itLPu1" } + rewards { term = 100000 term-after-capped-reward-feature = 5 @@ -49,6 +51,7 @@ waves { min-increment = 50000000 voting-interval = 1 } + include "genesis.conf" include "/etc/it/genesis.conf" } diff --git a/local-network/deploy/deploy.py b/local-network/deploy/deploy.py index 90eef034..49a94de8 100644 --- a/local-network/deploy/deploy.py +++ b/local-network/deploy/deploy.py @@ -23,8 +23,14 @@ log.info(f"Wait for {min_peers} peers, now: {r}") sleep(2) +log.info(f"Registry address: {network.cl_registry.oracleAddress}") log.info(f"Chain contract address: {network.cl_chain_contract.oracleAddress}") +log.info("Approve chain contract on registry") +network.cl_registry.storeData( + f"unit_{network.cl_chain_contract.oracleAddress}_approved", "boolean", True +) + script_info = network.cl_chain_contract.oracleAcc.scriptInfo() if script_info["script"] is None: log.info("Set chain contract script") diff --git a/local-network/deploy/local/network.py b/local-network/deploy/local/network.py index ac808767..68723222 100644 --- a/local-network/deploy/local/network.py +++ b/local-network/deploy/local/network.py @@ -28,9 +28,13 @@ class Miner: class ExtendedNetwork(Network): @cached_property - def cl_dao(self) -> ChainContract: + def cl_dao(self) -> pw.Address: return pw.Address(seed="devnet dao", nonce=0) + @cached_property + def cl_registry(self) -> pw.Oracle: + return pw.Oracle(seed="devnet registry") + @cached_property def cl_chain_contract(self) -> ChainContract: return ChainContract(seed="devnet cc", nonce=0) diff --git a/src/main/scala/units/ClientConfig.scala b/src/main/scala/units/ClientConfig.scala index b35e5473..89889984 100644 --- a/src/main/scala/units/ClientConfig.scala +++ b/src/main/scala/units/ClientConfig.scala @@ -3,9 +3,6 @@ package units import com.wavesplatform.account.Address import com.wavesplatform.common.utils.EitherExt2 import com.wavesplatform.settings.* -import net.ceedubs.ficus.Ficus.* -import net.ceedubs.ficus.readers.ArbitraryTypeReader.arbitraryTypeValueReader -import net.ceedubs.ficus.readers.{Generated, ValueReader} import units.client.JsonRpcClient import scala.concurrent.duration.FiniteDuration @@ -29,7 +26,3 @@ case class ClientConfig( apiRequestRetryWaitTime = apiRequestRetryWaitTime ) } - -object ClientConfig { - implicit val valueReader: Generated[ValueReader[ClientConfig]] = arbitraryTypeValueReader -} diff --git a/src/main/scala/units/ConsensusClient.scala b/src/main/scala/units/ConsensusClient.scala index d8b24dcb..5781a75c 100644 --- a/src/main/scala/units/ConsensusClient.scala +++ b/src/main/scala/units/ConsensusClient.scala @@ -1,14 +1,17 @@ package units +import com.typesafe.config.Config import com.typesafe.scalalogging.StrictLogging import com.wavesplatform.block.{Block, MicroBlock} import com.wavesplatform.common.state.ByteStr +import com.wavesplatform.common.utils.EitherExt2 import com.wavesplatform.events.BlockchainUpdateTriggers import com.wavesplatform.extensions.{Extension, Context as ExtensionContext} import com.wavesplatform.state.{Blockchain, StateSnapshot} import io.netty.channel.group.DefaultChannelGroup import monix.execution.{CancelableFuture, Scheduler} -import net.ceedubs.ficus.Ficus.* +import pureconfig.ConfigSource +import pureconfig.generic.auto.* import units.ConsensusClient.ChainHandler import units.client.engine.EngineApiClient import units.network.* @@ -28,15 +31,18 @@ class ConsensusClient(context: ExtensionContext) extends StrictLogging with Exte private val chainHandlers: Seq[ChainHandler] = { val defaultConfig = context.settings.config.getConfig("units.defaults") + def load(cfg: Config): ClientConfig = + ConfigSource.fromConfig(cfg.withFallback(defaultConfig).resolve()).loadOrThrow[ClientConfig] + val legacyChainConfig = - Try(context.settings.config.getConfig("waves.l2")).toOption.map(_.withFallback(defaultConfig).as[ClientConfig]).tapEach { _ => + Try(context.settings.config.getConfig("waves.l2")).toOption.map(load).tapEach { _ => logger.info("Consensus client settings at waves.l2 path have been deprecated, please update your config file") } val newChainConfigs = context.settings.config .getConfigList("units.chains") .asScala - .map(cfg => cfg.withFallback(defaultConfig).resolve().as[ClientConfig]) + .map(load) val allChainConfigs = legacyChainConfig ++ newChainConfigs @@ -93,6 +99,7 @@ object ConsensusClient { config, context.time, context.wallet, + context.settings.blockchainSettings.functionalitySettings.unitsRegistryAddressParsed.explicitGet(), blockObserver.loadBlock, context.broadcastTransaction, eluScheduler, diff --git a/src/main/scala/units/ELUpdater.scala b/src/main/scala/units/ELUpdater.scala index e829acab..f16e130d 100644 --- a/src/main/scala/units/ELUpdater.scala +++ b/src/main/scala/units/ELUpdater.scala @@ -10,9 +10,9 @@ import com.wavesplatform.crypto import com.wavesplatform.lang.ValidationError import com.wavesplatform.lang.v1.compiler.Terms.FUNCTION_CALL import com.wavesplatform.network.ChannelGroupExt -import com.wavesplatform.state.Blockchain import com.wavesplatform.state.diffs.FeeValidation.{FeeConstants, FeeUnit, ScriptExtraFee} import com.wavesplatform.state.diffs.TransactionDiffer.TransactionValidationError +import com.wavesplatform.state.{Blockchain, BooleanDataEntry} import com.wavesplatform.transaction.TxValidationError.InvokeRejectError import com.wavesplatform.transaction.smart.InvokeScriptTransaction import com.wavesplatform.transaction.smart.script.trace.TracedResult @@ -50,6 +50,7 @@ class ELUpdater( config: ClientConfig, time: Time, wallet: Wallet, + registryAddress: Option[Address], requestBlockFromPeers: BlockHash => CancelableFuture[BlockWithChannel], broadcastTx: Transaction => TracedResult[ValidationError, Boolean], scheduler: Scheduler, @@ -147,23 +148,6 @@ class ELUpdater( } } - private def cleanPriorityPool(): Unit = { - // A transaction moves to priority pool when a new key block references one of the previous micro blocks. - // When we add a new fresh transaction (extendMainChain) to UTX, it is validated against a stale transaction changes. - // Removing here, because we have these transactions in PP after the onProcessBlock trigger - utx.getPriorityPool.foreach { pp => - val staleTxs = pp.priorityTransactions.filter { - case tx: InvokeScriptTransaction => tx.dApp == contractAddress - case _ => false - } - - if (staleTxs.nonEmpty) { - logger.debug(s"Removing stale transactions: ${staleTxs.map(_.id()).mkString(", ")}") - utx.removeAll(staleTxs) - } - } - } - private def callContract(fc: FUNCTION_CALL, blockData: EcBlock, invoker: KeyPair): JobResult[Unit] = { val extraFee = if (blockchain.hasPaidVerifier(invoker.toAddress)) ScriptExtraFee else 0 @@ -180,7 +164,6 @@ class ELUpdater( blockchain.settings.addressSchemeCharacter.toByte ).signWith(invoker.privateKey) logger.info(s"Invoking $contractAddress '${fc.function.funcName}' for block ${blockData.hash}->${blockData.parentHash}, txId=${tx.id()}") - cleanPriorityPool() broadcastTx(tx).resultE match { case Right(true) => Either.unit @@ -250,7 +233,7 @@ class ELUpdater( ) } case Working(_, _, _, _, _, _: Mining | _: FollowingChain, _, _) => - // a new epoch started and we trying to apply a previous epoch payload: + // a new epoch started, and we're trying to apply a previous epoch payload: // Mining - we mine again // FollowingChain - we validate case other => logger.debug(s"Unexpected state $other attempting to finish building $payloadId") @@ -485,10 +468,32 @@ class ELUpdater( } private def handleConsensusLayerChanged(): Unit = { - state match { - case Starting => updateStartingState() - case w: Working[ChainStatus] => updateWorkingState(w) - case other => logger.debug(s"Unprocessed state: $other") + def stopMining(): Unit = setState("26", Starting) + + isChainEnabled match { + case Left(e) => + logger.warn(s"$contractAddress chain is disabled: $e") + stopMining() + + case Right(false) => + logger.warn(s"$contractAddress chain is disabled") + stopMining() + + case Right(true) => + state match { + case Starting => updateStartingState() + case w: Working[ChainStatus] => updateWorkingState(w) + case other => logger.debug(s"Unprocessed state: $other") + } + } + } + + private def isChainEnabled: Either[String, Boolean] = registryAddress.fold(true.asRight[String]) { registryAddress => + val key = registryKey(contractAddress) + blockchain.accountData(registryAddress, key) match { + case Some(BooleanDataEntry(_, isEnabled)) => isEnabled.asRight + case None => false.asRight + case Some(x) => s"Expected '$key' to be a boolean, got: $x".asLeft } } @@ -1572,7 +1577,7 @@ object ELUpdater { case class ChainSwitchInfo(prevChainId: Long, referenceBlock: ContractBlock) - /** We haven't received a EC-block {@link missedBlock} of a previous epoch when started a mining on a new epoch. We can return to the main chain, if + /** We haven't received an EC-block [[missedBlock]] of a previous epoch when started a mining on a new epoch. We can return to the main chain, if we * get a missed EC-block. */ case class ReturnToMainChainInfo(missedBlock: ContractBlock, missedBlockParent: EcBlock, chainId: Long) @@ -1599,4 +1604,6 @@ object ELUpdater { val msg = hitSource.arr ++ HexBytesConverter.toBytes(parentHash) HexBytesConverter.toHex(crypto.secureHash(msg)) } + + def registryKey(chainContract: Address): String = s"unit_${chainContract}_approved" } diff --git a/src/main/scala/units/client/JsonRpcClient.scala b/src/main/scala/units/client/JsonRpcClient.scala index d046a9b8..3251d056 100644 --- a/src/main/scala/units/client/JsonRpcClient.scala +++ b/src/main/scala/units/client/JsonRpcClient.scala @@ -2,10 +2,9 @@ package units.client import cats.Id import cats.syntax.either.* -import net.ceedubs.ficus.Ficus.* -import net.ceedubs.ficus.readers.ArbitraryTypeReader.arbitraryTypeValueReader -import net.ceedubs.ficus.readers.{Generated, ValueReader} import play.api.libs.json.{JsError, JsValue, Reads, Writes} +import pureconfig.* +import pureconfig.generic.semiauto.* import sttp.client3.* import sttp.client3.playJson.* import units.ClientError @@ -79,7 +78,7 @@ object JsonRpcClient { } object Config { - implicit val configValueReader: Generated[ValueReader[Config]] = arbitraryTypeValueReader + implicit val configValueReader: ConfigReader[Config] = deriveReader } def newRequestId: Int = ThreadLocalRandom.current().nextInt(10000, 100000) diff --git a/src/test/scala/units/BaseIntegrationTestSuite.scala b/src/test/scala/units/BaseIntegrationTestSuite.scala index 4acfd31a..b12468a4 100644 --- a/src/test/scala/units/BaseIntegrationTestSuite.scala +++ b/src/test/scala/units/BaseIntegrationTestSuite.scala @@ -1,5 +1,6 @@ package units +import com.wavesplatform.account.KeyPair import com.wavesplatform.database.{RDB, loadActiveLeases} import com.wavesplatform.db.WithDomain import com.wavesplatform.db.WithState.AddrWithBalance @@ -16,6 +17,7 @@ import units.eth.{EthAddress, Gwei} import units.test.CustomMatchers import units.util.HexBytesConverter +import java.nio.charset.StandardCharsets import java.util.concurrent.ThreadLocalRandom trait BaseIntegrationTestSuite @@ -27,15 +29,19 @@ trait BaseIntegrationTestSuite with EitherValues with OptionValues with CustomMatchers { - protected def defaultSettings = TestSettings.Default + protected val chainRegistryAccount: KeyPair = KeyPair("chain-registry".getBytes(StandardCharsets.UTF_8)) + protected val elMinerDefaultReward = Gwei.ofRawGwei(2_000_000_000L) protected val elBridgeAddress = EthAddress.unsafeFrom("0x0000000000000000000000000000000000006a7e") + protected def defaultSettings = TestSettings().withChainRegistry(chainRegistryAccount.toAddress) + protected def withExtensionDomain[R](settings: TestSettings = defaultSettings)(f: ExtensionDomain => R): R = withExtensionDomainUninitialized(settings) { d => log.debug("EL init") val txs = List( + d.ChainRegistry.approve(), d.ChainContract.setScript(), d.ChainContract.setup( d.ecGenesisBlock, @@ -51,7 +57,7 @@ trait BaseIntegrationTestSuite f(d) } - private def withExtensionDomainUninitialized[R](settings: TestSettings)(test: ExtensionDomain => R): R = + protected def withExtensionDomainUninitialized[R](settings: TestSettings = defaultSettings)(test: ExtensionDomain => R): R = withRocksDBWriter(settings.wavesSettings) { blockchain => var d: ExtensionDomain = null val bcu = new BlockchainUpdaterImpl( @@ -68,6 +74,7 @@ trait BaseIntegrationTestSuite blockchainUpdater = bcu, rocksDBWriter = blockchain, settings = settings.wavesSettings, + chainRegistryAccount = chainRegistryAccount, elBridgeAddress = elBridgeAddress, elMinerDefaultReward = elMinerDefaultReward ) @@ -76,6 +83,7 @@ trait BaseIntegrationTestSuite val balances = List( AddrWithBalance(TxHelpers.defaultAddress, 1_000_000.waves), + AddrWithBalance(d.chainRegistryAddress, 10.waves), AddrWithBalance(d.chainContractAddress, 10.waves) ) ++ settings.finalAdditionalBalances diff --git a/src/test/scala/units/BlockBriefValidationTestSuite.scala b/src/test/scala/units/BlockBriefValidationTestSuite.scala index ada4ebf5..b2dbc291 100644 --- a/src/test/scala/units/BlockBriefValidationTestSuite.scala +++ b/src/test/scala/units/BlockBriefValidationTestSuite.scala @@ -7,7 +7,7 @@ import units.eth.EthAddress class BlockBriefValidationTestSuite extends BaseIntegrationTestSuite { private val miner = ElMinerSettings(TxHelpers.signer(1)) - override protected val defaultSettings: TestSettings = TestSettings.Default.copy( + override protected val defaultSettings: TestSettings = super.defaultSettings.copy( initialMiners = List(miner) ) diff --git a/src/test/scala/units/BlockFullValidationTestSuite.scala b/src/test/scala/units/BlockFullValidationTestSuite.scala index 99c9a941..d589804e 100644 --- a/src/test/scala/units/BlockFullValidationTestSuite.scala +++ b/src/test/scala/units/BlockFullValidationTestSuite.scala @@ -16,7 +16,7 @@ class BlockFullValidationTestSuite extends BaseIntegrationTestSuite { private val reliable = ElMinerSettings(TxHelpers.signer(1)) private val malfunction = ElMinerSettings(TxHelpers.signer(2)) // Prevents a block finalization - override protected val defaultSettings: TestSettings = TestSettings.Default.copy( + override protected val defaultSettings: TestSettings = super.defaultSettings.copy( initialMiners = List(reliable, malfunction) ) diff --git a/src/test/scala/units/BlockIssuesForgingTestSuite.scala b/src/test/scala/units/BlockIssuesForgingTestSuite.scala index d4322398..848218cd 100644 --- a/src/test/scala/units/BlockIssuesForgingTestSuite.scala +++ b/src/test/scala/units/BlockIssuesForgingTestSuite.scala @@ -13,11 +13,11 @@ import scala.concurrent.duration.DurationInt class BlockIssuesForgingTestSuite extends BaseIntegrationTestSuite { private val transferReceiver = TxHelpers.secondSigner - private val thisMiner = ElMinerSettings(Wallet.generateNewAccount(TestSettings.Default.walletSeed, 0)) + private val thisMiner = ElMinerSettings(Wallet.generateNewAccount(super.defaultSettings.walletSeed, 0)) private val otherMiner1 = ElMinerSettings(TxHelpers.signer(2)) private val otherMiner2 = ElMinerSettings(TxHelpers.signer(3)) - override protected val defaultSettings: TestSettings = TestSettings.Default + override protected val defaultSettings: TestSettings = super.defaultSettings .copy( initialMiners = List(thisMiner, otherMiner1, otherMiner2), additionalBalances = List(AddrWithBalance(transferReceiver.toAddress, DefaultFees.ChainContract.withdrawFee)) diff --git a/src/test/scala/units/C2ETransfersTestSuite.scala b/src/test/scala/units/C2ETransfersTestSuite.scala index 5840f43e..514579d0 100644 --- a/src/test/scala/units/C2ETransfersTestSuite.scala +++ b/src/test/scala/units/C2ETransfersTestSuite.scala @@ -11,7 +11,7 @@ class C2ETransfersTestSuite extends BaseIntegrationTestSuite { private val validTransferRecipient = "1111111111111111111111111111111111111111" private val unrelatedAsset = TxHelpers.issue(issuer = transferSenderAccount) - override protected val defaultSettings: TestSettings = TestSettings.Default.copy( + override protected val defaultSettings: TestSettings = super.defaultSettings.copy( additionalBalances = List(AddrWithBalance(transferSenderAccount.toAddress)) ) diff --git a/src/test/scala/units/E2CTransfersTestSuite.scala b/src/test/scala/units/E2CTransfersTestSuite.scala index cefac22f..5f270369 100644 --- a/src/test/scala/units/E2CTransfersTestSuite.scala +++ b/src/test/scala/units/E2CTransfersTestSuite.scala @@ -25,10 +25,10 @@ class E2CTransfersTestSuite extends BaseIntegrationTestSuite { private val e2CTransfersRootHashHex = HexBytesConverter.toHex(Bridge.mkTransfersHash(ecBlockLogs).explicitGet()) private val transferProofs = Bridge.mkTransferProofs(List(transfer), 0).reverse // Contract requires from bottom to top - private val reliable = ElMinerSettings(Wallet.generateNewAccount(TestSettings.Default.walletSeed, 0)) + private val reliable = ElMinerSettings(Wallet.generateNewAccount(super.defaultSettings.walletSeed, 0)) private val malfunction = ElMinerSettings(TxHelpers.signer(2)) // Prevents block finalization - override protected val defaultSettings: TestSettings = TestSettings.Default.copy( + override protected val defaultSettings: TestSettings = super.defaultSettings.copy( initialMiners = List(reliable), additionalBalances = List(AddrWithBalance(transferReceiver.toAddress, DefaultFees.ChainContract.withdrawFee)) ) diff --git a/src/test/scala/units/ExtensionDomain.scala b/src/test/scala/units/ExtensionDomain.scala index 3c9eeeed..f78b8687 100644 --- a/src/test/scala/units/ExtensionDomain.scala +++ b/src/test/scala/units/ExtensionDomain.scala @@ -33,10 +33,11 @@ import monix.execution.ExecutionModel import monix.execution.schedulers.TestScheduler import monix.reactive.Observable import monix.reactive.subjects.PublishSubject -import net.ceedubs.ficus.Ficus.* import org.scalatest.exceptions.TestFailedException import org.web3j.abi.datatypes.generated.Uint256 import play.api.libs.json.* +import pureconfig.ConfigSource +import pureconfig.generic.auto.* import units.ELUpdater.* import units.ELUpdater.State.{ChainStatus, Working} import units.ExtensionDomain.* @@ -58,6 +59,7 @@ class ExtensionDomain( blockchainUpdater: BlockchainUpdaterImpl, rocksDBWriter: RocksDBWriter, settings: WavesSettings, + override val chainRegistryAccount: KeyPair, elBridgeAddress: EthAddress, elMinerDefaultReward: Gwei ) extends Domain(rdb, blockchainUpdater, rocksDBWriter, settings) @@ -67,7 +69,7 @@ class ExtensionDomain( with ScorexLogging { self => override val chainContractAccount: KeyPair = KeyPair("chain-contract".getBytes(StandardCharsets.UTF_8)) - val l2Config = settings.config.as[ClientConfig]("units.defaults") + val l2Config = ConfigSource.fromConfig(settings.config).at("units.defaults").loadOrThrow[ClientConfig] require(l2Config.chainContractAddress == chainContractAddress, "Check settings") val ecGenesisBlock = EcBlock( diff --git a/src/test/scala/units/RegistryTestSuite.scala b/src/test/scala/units/RegistryTestSuite.scala new file mode 100644 index 00000000..9d5fa8ff --- /dev/null +++ b/src/test/scala/units/RegistryTestSuite.scala @@ -0,0 +1,67 @@ +package units + +import com.wavesplatform.state.StringDataEntry +import com.wavesplatform.transaction.{DataTransaction, TxHelpers} +import com.wavesplatform.wallet.Wallet + +class RegistryTestSuite extends BaseIntegrationTestSuite { + private val miner = ElMinerSettings(Wallet.generateNewAccount(super.defaultSettings.walletSeed, 0)) + private val irrelevantChainAddress = TxHelpers.signer(10).toAddress + + override protected val defaultSettings: TestSettings = super.defaultSettings + .copy(initialMiners = List(miner)) + .withEnabledElMining + + "Mining doesn't start when chains registry" - { + def noMiningTest(registryTxn: ExtensionDomain => List[DataTransaction]): Unit = run(0)(registryTxn(_)) + + "doesn't have a key" in noMiningTest(_ => Nil) + + "has only an irrelevant chain" in noMiningTest { d => + d.ChainRegistry.approve(irrelevantChainAddress) :: Nil + } + + "has an invalid key" in noMiningTest { d => + val wrongTypeData = StringDataEntry(ELUpdater.registryKey(d.chainContractAddress), "true") + d.ChainRegistry.setStatus(wrongTypeData) :: Nil + } + + "has a rejected chain" in noMiningTest(_.ChainRegistry.reject() :: Nil) + } + + "Mining starts when chain registry has an approved chain" in run(1) { d => + List( + d.ChainRegistry.approve(irrelevantChainAddress), + d.ChainRegistry.approve() + ) + } + + private def run(miningAttempts: Int)(registryTxn: ExtensionDomain => List[DataTransaction]): Unit = { + val settings = defaultSettings + withExtensionDomainUninitialized(settings) { d => + log.debug("EL init") + val txs = { + registryTxn(d) ++ + List( + d.ChainContract.setScript(), + d.ChainContract.setup( + d.ecGenesisBlock, + elMinerDefaultReward.amount.longValue(), + defaultSettings.daoRewardAccount.map(_.toAddress), + defaultSettings.daoRewardAmount + ) + ) ++ + settings.initialMiners.map { x => d.ChainContract.join(x.account, x.elRewardAddress) } + } + + d.appendBlock(txs*) + d.advanceConsensusLayerChanged() + + step("Start new epoch for ecBlock") + d.advanceNewBlocks(miner.address) + d.advanceConsensusLayerChanged() + + d.ecClients.miningAttempts shouldBe miningAttempts + } + } +} diff --git a/src/test/scala/units/TestSettings.scala b/src/test/scala/units/TestSettings.scala index 6aa28955..f165691f 100644 --- a/src/test/scala/units/TestSettings.scala +++ b/src/test/scala/units/TestSettings.scala @@ -1,7 +1,7 @@ package units import com.typesafe.config.ConfigFactory -import com.wavesplatform.account.{KeyPair, SeedKeyPair} +import com.wavesplatform.account.{Address, KeyPair, SeedKeyPair} import com.wavesplatform.db.WithState.AddrWithBalance import com.wavesplatform.settings.WavesSettings import com.wavesplatform.test.{DomainPresets, NumericExt} @@ -21,15 +21,23 @@ case class TestSettings( def walletSeed: Array[Byte] = wavesSettings.walletSettings.seed.getOrElse(throw new RuntimeException("No wallet seed")).arr - def withEnabledElMining: TestSettings = copy(wavesSettings = Waves.WithMining) + def withEnabledElMining: TestSettings = copy(wavesSettings = + wavesSettings.copy(config = ConfigFactory.parseString("units.defaults.mining-enable = true").withFallback(wavesSettings.config)) + ) + + def withChainRegistry(address: Address): TestSettings = copy(wavesSettings = Waves.withChainRegistry(wavesSettings, Some(address))) } object TestSettings { - val Default = TestSettings() - private object Waves { - val Default = DomainPresets.TransactionStateSnapshot - val WithMining = Default.copy(config = ConfigFactory.parseString("units.defaults.mining-enable = true").withFallback(Default.config)) + val Default = withChainRegistry(DomainPresets.TransactionStateSnapshot, None) + + def withChainRegistry(settings: WavesSettings, address: Option[Address]): WavesSettings = + settings.copy(blockchainSettings = + settings.blockchainSettings.copy(functionalitySettings = + settings.blockchainSettings.functionalitySettings.copy(unitsRegistryAddress = address.map(_.toString)) + ) + ) } } diff --git a/src/test/scala/units/client/TestEcClients.scala b/src/test/scala/units/client/TestEcClients.scala index 0225f1b6..2128dd27 100644 --- a/src/test/scala/units/client/TestEcClients.scala +++ b/src/test/scala/units/client/TestEcClients.scala @@ -62,6 +62,9 @@ class TestEcClients private ( */ def fullValidatedBlocks: Set[BlockHash] = getLogsCalls.get() + private val forkChoiceUpdateWithPayloadIdCalls = AtomicInt(0) + def miningAttempts: Int = forkChoiceUpdateWithPayloadIdCalls.get() + val engineApi = new LoggedEngineApiClient( new EngineApiClient { override def forkChoiceUpdate(blockHash: BlockHash, finalizedBlockHash: BlockHash, requestId: Int): JobResult[PayloadStatus] = { @@ -87,7 +90,8 @@ class TestEcClients private ( prevRandao: String, withdrawals: Vector[Withdrawal], requestId: Int - ): JobResult[PayloadId] = + ): JobResult[PayloadId] = { + forkChoiceUpdateWithPayloadIdCalls.increment() forgingBlocks .get() .collectFirst { case fb if fb.testBlock.parentHash == lastBlockHash => fb } match { @@ -98,6 +102,7 @@ class TestEcClients private ( case Some(fb) => fb.payloadId.asRight } + } override def getPayload(payloadId: PayloadId, requestId: Int): JobResult[JsObject] = forgingBlocks.transformAndExtract(_.withoutFirst { fb => fb.payloadId == payloadId }) match { diff --git a/src/test/scala/units/client/contract/HasConsensusLayerDappTxHelpers.scala b/src/test/scala/units/client/contract/HasConsensusLayerDappTxHelpers.scala index c0c67fc7..4153c5b5 100644 --- a/src/test/scala/units/client/contract/HasConsensusLayerDappTxHelpers.scala +++ b/src/test/scala/units/client/contract/HasConsensusLayerDappTxHelpers.scala @@ -6,11 +6,12 @@ import com.wavesplatform.common.merkle.Digest import com.wavesplatform.common.state.ByteStr import com.wavesplatform.common.utils.EitherExt2 import com.wavesplatform.lang.v1.compiler.Terms +import com.wavesplatform.state.{BooleanDataEntry, DataEntry} import com.wavesplatform.test.NumericExt import com.wavesplatform.transaction.TxHelpers.defaultSigner import com.wavesplatform.transaction.smart.{InvokeScriptTransaction, SetScriptTransaction} -import com.wavesplatform.transaction.{Asset, TxHelpers} -import units.BlockHash +import com.wavesplatform.transaction.{Asset, DataTransaction, TxHelpers} +import units.{BlockHash, ELUpdater} import units.client.L2BlockLike import units.client.contract.HasConsensusLayerDappTxHelpers.* import units.client.contract.HasConsensusLayerDappTxHelpers.DefaultFees.ChainContract.* @@ -22,6 +23,23 @@ trait HasConsensusLayerDappTxHelpers { def chainContractAccount: KeyPair lazy val chainContractAddress: Address = chainContractAccount.toAddress + def chainRegistryAccount: KeyPair + lazy val chainRegistryAddress: Address = chainRegistryAccount.toAddress + + object ChainRegistry { + def approve(chainContract: Address = chainContractAddress): DataTransaction = + setStatus(BooleanDataEntry(ELUpdater.registryKey(chainContract), value = true)) + + def reject(chainContract: Address = chainContractAddress): DataTransaction = + setStatus(BooleanDataEntry(ELUpdater.registryKey(chainContract), value = false)) + + def setStatus(status: DataEntry[?]): DataTransaction = + TxHelpers.data( + account = chainRegistryAccount, + entries = List(status) + ) + } + object ChainContract { def setScript(): SetScriptTransaction = TxHelpers.setScript(chainContractAccount, CompiledChainContract.script, fee = setScriptFee) From 83ef4cc38102542e311ed1645fb458e4d70543f2 Mon Sep 17 00:00:00 2001 From: Vyatcheslav Suharnikov Date: Thu, 28 Nov 2024 13:01:10 +0400 Subject: [PATCH 2/9] local-network stabilization --- .../src/test/scala/com/wavesplatform/api/NodeHttpApi.scala | 2 +- .../src/test/scala/units/docker/WavesNodeContainer.scala | 1 + local-network/configs/wavesnode/genesis-template.conf | 4 ++-- local-network/configs/wavesnode/waves.conf | 4 +++- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/consensus-client-it/src/test/scala/com/wavesplatform/api/NodeHttpApi.scala b/consensus-client-it/src/test/scala/com/wavesplatform/api/NodeHttpApi.scala index bbae09a6..eba66b9e 100644 --- a/consensus-client-it/src/test/scala/com/wavesplatform/api/NodeHttpApi.scala +++ b/consensus-client-it/src/test/scala/com/wavesplatform/api/NodeHttpApi.scala @@ -52,7 +52,7 @@ class NodeHttpApi(apiUri: Uri, backend: SttpBackend[Identity, ?], apiKeyValue: S if (currHeight >= atLeast) currHeight else { Thread.sleep(patienceConfig.interval.toMillis) - val waitBlocks = (atLeast - currHeight).min(1) + val waitBlocks = (atLeast - currHeight).max(1) eventually(timeout(MaxBlockDelay * waitBlocks)) { val h = height()(subsequentLoggingOptions) h should be >= atLeast diff --git a/consensus-client-it/src/test/scala/units/docker/WavesNodeContainer.scala b/consensus-client-it/src/test/scala/units/docker/WavesNodeContainer.scala index f6af360e..61d3b9e0 100644 --- a/consensus-client-it/src/test/scala/units/docker/WavesNodeContainer.scala +++ b/consensus-client-it/src/test/scala/units/docker/WavesNodeContainer.scala @@ -41,6 +41,7 @@ class WavesNodeContainer( "NODE_NUMBER" -> s"$number", "WAVES_WALLET_SEED" -> Base58.encode(baseSeed.getBytes(StandardCharsets.UTF_8)), "JAVA_OPTS" -> List( + "-Dwaves.miner.quorum=0", s"-Dunits.defaults.chain-contract=$chainContractAddress", s"-Dunits.defaults.execution-client-address=$ecEngineApiUrl", "-Dlogback.file.level=TRACE", diff --git a/local-network/configs/wavesnode/genesis-template.conf b/local-network/configs/wavesnode/genesis-template.conf index 91aaa3ce..d0c505d0 100644 --- a/local-network/configs/wavesnode/genesis-template.conf +++ b/local-network/configs/wavesnode/genesis-template.conf @@ -24,7 +24,7 @@ genesis-generator { # Private key: 5r7KpS3MNXxRcz9jMbpjZKhaZVxDxF74H4VLW6ydi4aT # Public key: 2JYMTjUK7tC8NQi6TD6oWgy41YbrnXuoLzZydrFKTKt6 # Address: 3FSgXpgbT6m1speWgVx3cVxAZKmdr4barHU - { seed-text = "devnet-1", nonce = 1, amount = 998036000000000 } + { seed-text = "devnet-1", nonce = 1, amount = 900000000000000 } # Miner on wavesnode-2 # Seed text: devnet-2 @@ -33,7 +33,7 @@ genesis-generator { # Private key: F17jrRWmrR7en6eY6ptvnUTNqc9W8RSP34hpX7bNhbht # Public key: FuibB1rJ1uHVvvY6FNmhLqnbvQBNtziWbh7zh5c1CQCG # Address: 3FSrRN8X7cDsLyYTScS8Yf8KSwZgJBwf1jU - { seed-text = "devnet-2", nonce = 0, amount = 998036000000000 } + { seed-text = "devnet-2", nonce = 0, amount = 800900102030000 } # Additional addresses diff --git a/local-network/configs/wavesnode/waves.conf b/local-network/configs/wavesnode/waves.conf index 663b5e1e..d6620bfc 100644 --- a/local-network/configs/wavesnode/waves.conf +++ b/local-network/configs/wavesnode/waves.conf @@ -62,7 +62,7 @@ waves { micro-block-interval = 200ms max-transactions-in-micro-block = 500 min-micro-block-age = 0ms - quorum = 0 + quorum = 1 # Solves a simultaneous mining on start interval-after-last-block-then-generation-is-allowed = 120d } @@ -115,6 +115,8 @@ waves { minimum-peers = 0 } + ntp-server = "47.91.111.180" # TODO: set to null after https://github.com/wavesplatform/Waves/pull/3978 + # Nodes synchronization settings synchronization { # Timeout to receive all requested blocks From 900c1accfa061007d0970d77701b5817055e26a3 Mon Sep 17 00:00:00 2001 From: Sergey Nazarov Date: Mon, 2 Dec 2024 17:11:01 +0300 Subject: [PATCH 3/9] Mainnet launch (#28) --- docker/genesis-mainnet.json | 43 ++++++++++++++++++++++++++++++++ docker/geth-mainnet.toml | 28 +++++++++++++++++++++ docker/init-geth.sh | 6 ----- docker/services/besu.yml | 9 ++++--- docker/services/geth.yml | 22 +++++++++++----- docker/services/waves-node.yml | 7 +++--- docker/static-nodes-mainnet.json | 13 ++++++++++ docker/static-nodes-testnet.json | 0 docker/testnet.env | 2 ++ docker/waves-mainnet.conf | 42 +++++++++++++++++++++++++++++++ 10 files changed, 154 insertions(+), 18 deletions(-) create mode 100644 docker/genesis-mainnet.json create mode 100644 docker/geth-mainnet.toml delete mode 100755 docker/init-geth.sh create mode 100644 docker/static-nodes-mainnet.json create mode 100644 docker/static-nodes-testnet.json create mode 100644 docker/waves-mainnet.conf diff --git a/docker/genesis-mainnet.json b/docker/genesis-mainnet.json new file mode 100644 index 00000000..0824bd88 --- /dev/null +++ b/docker/genesis-mainnet.json @@ -0,0 +1,43 @@ +{ + "alloc": { + "0x0000000000000000000000000000000000006a7e": { + "code": "0x60806040526004361061006e575f3560e01c806396f396c31161004c57806396f396c3146100e3578063c4a4326d14610105578063e984df0e1461011d578063fccc281314610131575f80fd5b806339dd5d1b146100725780637157405a146100b957806378338413146100ce575b5f80fd5b34801561007d575f80fd5b506100a161008c36600461059e565b5f6020819052908152604090205461ffff1681565b60405161ffff90911681526020015b60405180910390f35b3480156100c4575f80fd5b506100a161040081565b6100e16100dc3660046105b5565b61015c565b005b3480156100ee575f80fd5b506100f761044e565b6040519081526020016100b0565b348015610110575f80fd5b506100f76402540be40081565b348015610128575f80fd5b506100f7610468565b34801561013c575f80fd5b506101445f81565b6040516001600160a01b0390911681526020016100b0565b61016c6402540be40060016105fc565b34101561017834610478565b61019061018b6402540be40060016105fc565b610478565b6040516020016101a1929190610630565b604051602081830303815290604052906101d75760405162461bcd60e51b81526004016101ce9190610688565b60405180910390fd5b506101ef6402540be400677fffffffffffffff6105fc565b3411156101fb34610478565b61021561018b6402540be400677fffffffffffffff6105fc565b6040516020016102269291906106bd565b604051602081830303815290604052906102535760405162461bcd60e51b81526004016101ce9190610688565b50435f8181526020819052604090205461ffff166104009081119061027790610478565b604051602001610287919061070c565b604051602081830303815290604052906102b45760405162461bcd60e51b81526004016101ce9190610688565b505f818152602081905260408120805461ffff16916102d283610786565b91906101000a81548161ffff021916908361ffff160217905550505f6402540be400346102ff91906107a6565b9050346103116402540be400836105fc565b1461031b34610478565b6103296402540be400610478565b60405160200161033a9291906107c5565b604051602081830303815290604052906103675760405162461bcd60e51b81526004016101ce9190610688565b506040515f90819034908281818185825af1925050503d805f81146103a7576040519150601f19603f3d011682016040523d82523d5f602084013e6103ac565b606091505b50509050806103fd5760405162461bcd60e51b815260206004820152601e60248201527f4661696c656420746f2073656e6420746f206275726e2061646472657373000060448201526064016101ce565b604080516bffffffffffffffffffffffff1986168152600784900b60208201527ffeadaf04de8d7c2594453835b9a93b747e20e7a09a7fdb9280579a6dbaf131a8910160405180910390a150505050565b6104656402540be400677fffffffffffffff6105fc565b81565b6104656402540be40060016105fc565b6060815f0361049e5750506040805180820190915260018152600360fc1b602082015290565b815f5b81156104c757806104b181610814565b91506104c09050600a836107a6565b91506104a1565b5f8167ffffffffffffffff8111156104e1576104e161082c565b6040519080825280601f01601f19166020018201604052801561050b576020820181803683370190505b509050815b851561059557610521600182610840565b90505f61052f600a886107a6565b61053a90600a6105fc565b6105449088610840565b61054f906030610853565b90505f8160f81b90508084848151811061056b5761056b61086c565b60200101906001600160f81b03191690815f1a90535061058c600a896107a6565b97505050610510565b50949350505050565b5f602082840312156105ae575f80fd5b5035919050565b5f602082840312156105c5575f80fd5b81356bffffffffffffffffffffffff19811681146105e1575f80fd5b9392505050565b634e487b7160e01b5f52601160045260245ffd5b8082028115828204841417610613576106136105e8565b92915050565b5f81518060208401855e5f93019283525090919050565b6a029b2b73a103b30b63ab2960ad1b81525f61064f600b830185610619565b7f206d7573742062652067726561746572206f7220657175616c20746f20000000815261067f601d820185610619565b95945050505050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b6a029b2b73a103b30b63ab2960ad1b81525f6106dc600b830185610619565b7f206d757374206265206c657373206f7220657175616c20746f20000000000000815261067f601a820185610619565b7f4d6178207472616e7366657273206c696d6974206f662000000000000000000081525f61073d6017830184610619565b7f207265616368656420696e207468697320626c6f636b2e2054727920746f207381527232b732103a3930b739b332b9399030b3b0b4b760691b60208201526033019392505050565b5f61ffff821661ffff810361079d5761079d6105e8565b60010192915050565b5f826107c057634e487b7160e01b5f52601260045260245ffd5b500490565b6a029b2b73a103b30b63ab2960ad1b81525f6107e4600b830185610619565b7f206d7573742062652061206d756c7469706c65206f6620000000000000000000815261067f6017820185610619565b5f60018201610825576108256105e8565b5060010190565b634e487b7160e01b5f52604160045260245ffd5b81810381811115610613576106136105e8565b60ff8181168382160190811115610613576106136105e8565b634e487b7160e01b5f52603260045260245ffdfea2646970667358221220106399f534da089226c14e2f183f8421d059a924c65c97d7e4f3e931c54fe1bb64736f6c634300081a0033", + "balance": "0x0" + } + }, + "baseFeePerGas": "0x3b9aca00", + "blobGasUsed": null, + "coinbase": "0x0000000000000000000000000000000000000000", + "config": { + "chainId": 88811, + "arrowGlacierBlock": 0, + "berlinBlock": 0, + "byzantiumBlock": 0, + "cancunTime": 0, + "constantinopleBlock": 0, + "daoForkBlock": 0, + "eip150Block": 0, + "eip155Block": 0, + "eip158Block": 0, + "ethash": {}, + "grayGlacierBlock": 0, + "homesteadBlock": 0, + "istanbulBlock": 0, + "londonBlock": 0, + "muirGlacierBlock": 0, + "petersburgBlock": 0, + "shanghaiTime": 0, + "terminalTotalDifficulty": 0, + "terminalTotalDifficultyPassed": true + }, + "difficulty": "0x0", + "excessBlobGas": null, + "extraData": "0x", + "gasLimit": "0x989680", + "gasUsed": "0x0", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "nonce": "0x0", + "number": "0x0", + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "timestamp": "0x6720960b" +} diff --git a/docker/geth-mainnet.toml b/docker/geth-mainnet.toml new file mode 100644 index 00000000..60f5f265 --- /dev/null +++ b/docker/geth-mainnet.toml @@ -0,0 +1,28 @@ +[Node.P2P] +BootstrapNodes = [ + "enode://02718d9a9c6f829c14ea3fd143e526130c70ae43956682cd234046ec932b1c21ca321c484bbb6aa766322ee7e0089d3405747f31d156ec0d67cd80482aede5d7@81.82.238.146:30301", + "enode://02884ba9163fe92e1aa5a940a050d12c7d857fed092e43d242ebb63472a3e16e77d3b626d50ad790ed454e0e93607ba7ccebd5ac8423d5745df5066708709ac9@185.241.151.12:30303", + "enode://1937134aff8287fddfc80d2583c9218521b15719dc7782ec85322493b973d02a76edf23ad30657f2d827e04a573e8a5bb2a0052a696a960365c2f13e69cbc0f3@95.216.152.163:30303", + "enode://5355b769f711ab1951c788d664d0ccbf4bc989013ea3a4f419ab01d9930b524956be65442fa4b72e7de9c470ceeac796235fb198ad9ef49dab559139f17282e2@38.242.222.27:30303", + "enode://6b534a07943cbca55d6dff834cac2c77f3e82895f51b25fa8cca1689b5cc0921f68453165fa5c736e55e4c61d0b73795445ed2099c09008358805467d07d2066@81.82.238.146:30302", + "enode://85389460716e3e3247b51139de2f11f1b886c7eb3dc849e2e9673447c81922f9955b2d271834cae9c1625e69f7805e2c89362d4dd8cb0ca972668d7262252790@63.250.53.184:30303", + "enode://b232ad7ca7bd6156e1adaa28ee0d064f3d973a67c0ad507a1b9dc32b3d64b307c754bc48c274aa96852f0041c2f85792681495e21f5baa62f06d3db8097af258@142.132.251.180:30303", + "enode://ded10bb464eea90d2a61ab7fef15531dca698845d93f7fc191a5383c22b09de282982872515f398ae527d300c2d5324bae61199dbb354843e6792f2d13b87880@172.104.241.53:30303", + "enode://e15d6f32cddc2a8e69885fc5c445b8ca7bafd91e9a7a834e89ed688150aa55df20fc7ff14d1fc5dd1e266c2b6a2f9dc75b1d6ed5f80ac71cb27f6ba8af12ba4b@213.238.172.133:30303", + "enode://e8f7dbec4b146ef0ed1852cd05e3c0654f78a5784a7584f45bc0073bf6206d55764600b586148dfca42bd711c1c1bc02cb20abb2210320f830f003aacf074396@95.217.59.114:30303", + "enode://edab526402907ccbbdf51950f09b964d9ebc1b51e1a9a1dca44fdaf823d85f84e513e95503f1e4d9e4e90355674819d52e46b014e054da5f199d5406ae6a5e22@185.31.163.22:30303" +] +BootstrapNodesV5 = [] +StaticNodes = [ + "enode://02718d9a9c6f829c14ea3fd143e526130c70ae43956682cd234046ec932b1c21ca321c484bbb6aa766322ee7e0089d3405747f31d156ec0d67cd80482aede5d7@81.82.238.146:30301", + "enode://02884ba9163fe92e1aa5a940a050d12c7d857fed092e43d242ebb63472a3e16e77d3b626d50ad790ed454e0e93607ba7ccebd5ac8423d5745df5066708709ac9@185.241.151.12:30303", + "enode://1937134aff8287fddfc80d2583c9218521b15719dc7782ec85322493b973d02a76edf23ad30657f2d827e04a573e8a5bb2a0052a696a960365c2f13e69cbc0f3@95.216.152.163:30303", + "enode://5355b769f711ab1951c788d664d0ccbf4bc989013ea3a4f419ab01d9930b524956be65442fa4b72e7de9c470ceeac796235fb198ad9ef49dab559139f17282e2@38.242.222.27:30303", + "enode://6b534a07943cbca55d6dff834cac2c77f3e82895f51b25fa8cca1689b5cc0921f68453165fa5c736e55e4c61d0b73795445ed2099c09008358805467d07d2066@81.82.238.146:30302", + "enode://85389460716e3e3247b51139de2f11f1b886c7eb3dc849e2e9673447c81922f9955b2d271834cae9c1625e69f7805e2c89362d4dd8cb0ca972668d7262252790@63.250.53.184:30303", + "enode://b232ad7ca7bd6156e1adaa28ee0d064f3d973a67c0ad507a1b9dc32b3d64b307c754bc48c274aa96852f0041c2f85792681495e21f5baa62f06d3db8097af258@142.132.251.180:30303", + "enode://ded10bb464eea90d2a61ab7fef15531dca698845d93f7fc191a5383c22b09de282982872515f398ae527d300c2d5324bae61199dbb354843e6792f2d13b87880@172.104.241.53:30303", + "enode://e15d6f32cddc2a8e69885fc5c445b8ca7bafd91e9a7a834e89ed688150aa55df20fc7ff14d1fc5dd1e266c2b6a2f9dc75b1d6ed5f80ac71cb27f6ba8af12ba4b@213.238.172.133:30303", + "enode://e8f7dbec4b146ef0ed1852cd05e3c0654f78a5784a7584f45bc0073bf6206d55764600b586148dfca42bd711c1c1bc02cb20abb2210320f830f003aacf074396@95.217.59.114:30303", + "enode://edab526402907ccbbdf51950f09b964d9ebc1b51e1a9a1dca44fdaf823d85f84e513e95503f1e4d9e4e90355674819d52e46b014e054da5f199d5406ae6a5e22@185.31.163.22:30303" +] diff --git a/docker/init-geth.sh b/docker/init-geth.sh deleted file mode 100755 index 39e25e74..00000000 --- a/docker/init-geth.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/sh -if [ ! -d /root/.ethereum/geth ] ; then - geth init /tmp/genesis.json -else - echo geth already initialized -fi diff --git a/docker/services/besu.yml b/docker/services/besu.yml index bc75690f..5ddef47c 100644 --- a/docker/services/besu.yml +++ b/docker/services/besu.yml @@ -4,6 +4,7 @@ services: image: hyperledger/besu:latest pull_policy: always stop_grace_period: 5m + restart: unless-stopped command: - --logging=ALL - --host-allowlist=* @@ -19,11 +20,11 @@ services: - --data-path=/var/lib/besu - --genesis-file=/etc/besu/genesis.json - --data-storage-format=BONSAI - - --network-id=${NETWORK_ID} - - --target-gas-limit=15000000 + - --static-nodes-file=/etc/besu/static-nodes.json volumes: - - ../genesis-${NETWORK}.json:/etc/besu/genesis.json - ../data/secrets:/etc/secrets:ro + - ../genesis-${NETWORK}.json:/etc/besu/genesis.json + - ../static-nodes-${NETWORK}.json:/etc/besu/static-nodes.json - ../log4j2.xml:/etc/besu/log4j2.xml - ../data/besu:/var/lib/besu - ../logs/besu:/opt/besu/logs @@ -32,3 +33,5 @@ services: - '30303:30303/udp' environment: - LOG4J_CONFIGURATION_FILE=/etc/besu/log4j2.xml + - BESU_TARGET_GAS_LIMIT=${GAS_LIMIT} + - BESU_NETWORK_ID=${NETWORK_ID} diff --git a/docker/services/geth.yml b/docker/services/geth.yml index f64288de..a86449d2 100644 --- a/docker/services/geth.yml +++ b/docker/services/geth.yml @@ -2,17 +2,26 @@ services: geth-init: container_name: geth-init image: ethereum/client-go:stable - entrypoint: /tmp/init-geth.sh + entrypoint: /bin/sh -c + command: + - | + if [ ! -d /root/.ethereum/geth ] ; then + geth init /tmp/genesis.json + else + echo geth already initialized + fi volumes: - ../genesis-${NETWORK}.json:/tmp/genesis.json - ../data/geth:/root/.ethereum - - ../init-geth.sh:/tmp/init-geth.sh geth: container_name: geth image: ethereum/client-go:stable pull_policy: always stop_grace_period: 5m + restart: unless-stopped command: + - --config=/etc/config.toml + - --syncmode=full - --verbosity=4 - --http - --http.addr=0.0.0.0 @@ -26,11 +35,11 @@ services: - --ws.origins=* - --authrpc.addr=0.0.0.0 - --authrpc.vhosts=* - - --discovery.dns=enrtree://AIRIZFFZSCSIVHXTKA44WYZQJMR75FLTGWJ5TUNEW5IP7QKZDLBRK@${NETWORK}-nodes.unit0.dev - - --networkid=${NETWORK_ID} - --authrpc.jwtsecret=/etc/secrets/jwtsecret - --nodekey=/etc/secrets/p2p-key - - --miner.gaslimit=15000000 + environment: + - GETH_MINER_GASLIMIT=${GAS_LIMIT} + - GETH_NETWORKID=${NETWORK_ID} logging: driver: local options: @@ -39,11 +48,12 @@ services: volumes: - ../data/secrets:/etc/secrets:ro - ../data/geth:/root/.ethereum + - ../geth-${NETWORK}:/etc/config.toml ports: - '30303:30303/tcp' - '30303:30303/udp' healthcheck: test: 'wget -qO /dev/null --header "content-type: application/json" --post-data {\"jsonrpc\":\"2.0\",\"method\":\"eth_blockNumber\",\"params\":[],\"id\":1} http://127.0.0.1:8545' - interval: 5s + interval: 10s timeout: 1s retries: 10 diff --git a/docker/services/waves-node.yml b/docker/services/waves-node.yml index 029df6f7..377bbe2a 100644 --- a/docker/services/waves-node.yml +++ b/docker/services/waves-node.yml @@ -3,10 +3,11 @@ services: container_name: waves-node image: ghcr.io/unitsnetwork/consensus-client:testnet stop_grace_period: 5m + restart: unless-stopped ports: - - "6869:6869" - - "6868:6868" - - "6865:6865" + - 127.0.0.1:6869:6869 + - 6868:6868 + - 6865:6865 environment: - JAVA_OPTS=-Dwaves.config.directory=/etc/waves -Dlogback.file.level=TRACE -Dwaves.blockchain.type=$NETWORK env_file: diff --git a/docker/static-nodes-mainnet.json b/docker/static-nodes-mainnet.json new file mode 100644 index 00000000..ce758e65 --- /dev/null +++ b/docker/static-nodes-mainnet.json @@ -0,0 +1,13 @@ +[ + "enode://02718d9a9c6f829c14ea3fd143e526130c70ae43956682cd234046ec932b1c21ca321c484bbb6aa766322ee7e0089d3405747f31d156ec0d67cd80482aede5d7@81.82.238.146:30301", + "enode://02884ba9163fe92e1aa5a940a050d12c7d857fed092e43d242ebb63472a3e16e77d3b626d50ad790ed454e0e93607ba7ccebd5ac8423d5745df5066708709ac9@185.241.151.12:30303", + "enode://1937134aff8287fddfc80d2583c9218521b15719dc7782ec85322493b973d02a76edf23ad30657f2d827e04a573e8a5bb2a0052a696a960365c2f13e69cbc0f3@95.216.152.163:30303", + "enode://5355b769f711ab1951c788d664d0ccbf4bc989013ea3a4f419ab01d9930b524956be65442fa4b72e7de9c470ceeac796235fb198ad9ef49dab559139f17282e2@38.242.222.27:30303", + "enode://6b534a07943cbca55d6dff834cac2c77f3e82895f51b25fa8cca1689b5cc0921f68453165fa5c736e55e4c61d0b73795445ed2099c09008358805467d07d2066@81.82.238.146:30302", + "enode://85389460716e3e3247b51139de2f11f1b886c7eb3dc849e2e9673447c81922f9955b2d271834cae9c1625e69f7805e2c89362d4dd8cb0ca972668d7262252790@63.250.53.184:30303", + "enode://b232ad7ca7bd6156e1adaa28ee0d064f3d973a67c0ad507a1b9dc32b3d64b307c754bc48c274aa96852f0041c2f85792681495e21f5baa62f06d3db8097af258@142.132.251.180:30303", + "enode://ded10bb464eea90d2a61ab7fef15531dca698845d93f7fc191a5383c22b09de282982872515f398ae527d300c2d5324bae61199dbb354843e6792f2d13b87880@172.104.241.53:30303", + "enode://e15d6f32cddc2a8e69885fc5c445b8ca7bafd91e9a7a834e89ed688150aa55df20fc7ff14d1fc5dd1e266c2b6a2f9dc75b1d6ed5f80ac71cb27f6ba8af12ba4b@213.238.172.133:30303", + "enode://e8f7dbec4b146ef0ed1852cd05e3c0654f78a5784a7584f45bc0073bf6206d55764600b586148dfca42bd711c1c1bc02cb20abb2210320f830f003aacf074396@95.217.59.114:30303", + "enode://edab526402907ccbbdf51950f09b964d9ebc1b51e1a9a1dca44fdaf823d85f84e513e95503f1e4d9e4e90355674819d52e46b014e054da5f199d5406ae6a5e22@185.31.163.22:30303" +] diff --git a/docker/static-nodes-testnet.json b/docker/static-nodes-testnet.json new file mode 100644 index 00000000..e69de29b diff --git a/docker/testnet.env b/docker/testnet.env index 52b00a8d..71db42c3 100644 --- a/docker/testnet.env +++ b/docker/testnet.env @@ -1,5 +1,7 @@ NETWORK=testnet NETWORK_ID=88817 WAVES_NODE_TAG=testnet +GAS_LIMIT=10000000 +BOOTNODES=enode://0a4d389579cfe536da57e2c1699d682d053eccac26412d1a23eca88fc4bdc0d3e2c45ef8fdfeca6eb20ee4ce0ded06fe37625c7e3bee7e097932d85a1b45308c@65.108.122.140:30303 #WAVES_DECLARED_ADDRESS=1.2.3.4:6868 #UNITS_DECLARED_ADDRESS=1.2.3.4:6865 diff --git a/docker/waves-mainnet.conf b/docker/waves-mainnet.conf new file mode 100644 index 00000000..96f0a2d4 --- /dev/null +++ b/docker/waves-mainnet.conf @@ -0,0 +1,42 @@ +waves { + extensions = [ + units.ConsensusClient + ] + + wallet { + seed = ${WAVES_WALLET_SEED} + password = ${WAVES_WALLET_PASSWORD} + } + + network { + bind-address = "0.0.0.0" + port = 6868 + declared-address = ${?WAVES_DECLARED_ADDRESS} + } + + rest-api { + enable = yes + bind-address = "0.0.0.0" + port = 6869 + api-key-hash = ${?WAVES_API_KEY_HASH} + } +} + +units { + chains = [ + { + chain-contract = 3PKgN8rfmvF7hK7RWJbpvkh59e1pQkUzero + execution-client-address = "http://execution-client:8551" + jwt-secret-file = /etc/secrets/jwtsecret + + network { + port = 6865 + declared-address = ${?UNITS_DECLARED_ADDRESS} + known-peers = [ + "mainnet-htz-fsn1-1.unit0.dev:6865" + ] + } + mining-enable = no + } + ] +} From 24d4733adca83c780b74b56e28151d14a5132598 Mon Sep 17 00:00:00 2001 From: Sergey Nazarov Date: Wed, 11 Dec 2024 18:55:04 +0300 Subject: [PATCH 4/9] bumped node version --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 11bf8ecf..6597c1a7 100644 --- a/build.sbt +++ b/build.sbt @@ -31,7 +31,7 @@ name := "consensus-client" maintainer := "Units Network Team" libraryDependencies ++= { - val node = "1.5-3977-SNAPSHOT" + val node = "1.5-SNAPSHOT" val sttp = "3.10.1" Seq( "com.wavesplatform" % "node-testkit" % node % Test, From 9deadcc31163be7907c6239f9e1fddda7b2a3eda Mon Sep 17 00:00:00 2001 From: Vyatcheslav Suharnikov Date: Fri, 13 Dec 2024 12:51:17 +0400 Subject: [PATCH 5/9] local-network: use main branch for units-network dependency --- local-network/deploy/pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/local-network/deploy/pyproject.toml b/local-network/deploy/pyproject.toml index 01fdf4f2..bb16f36d 100644 --- a/local-network/deploy/pyproject.toml +++ b/local-network/deploy/pyproject.toml @@ -8,7 +8,7 @@ version = "0.1" description = "Scripts and tests for a locally deployed Unit network" dependencies = [ "solc-select", - "units-network @ git+https://github.com/UnitsNetwork/examples.git@dao-rewards", + "units-network @ git+https://github.com/UnitsNetwork/examples.git", ] readme = "README.md" requires-python = ">=3.9" From 67b607a08c9261bb0a92336933baaf59a38a9ee6 Mon Sep 17 00:00:00 2001 From: Vyatcheslav Suharnikov Date: Fri, 13 Dec 2024 14:08:25 +0400 Subject: [PATCH 6/9] Simpler EC setup in docker-compose.yml --- local-network/configs/besu/besu.conf | 3 +-- local-network/configs/besu/besu.yml | 2 +- local-network/configs/besu/run-besu.sh | 4 +++- local-network/configs/geth/geth.yml | 2 +- local-network/configs/geth/run-geth.sh | 6 +++--- local-network/docker-compose.yml | 7 ++++--- 6 files changed, 13 insertions(+), 11 deletions(-) diff --git a/local-network/configs/besu/besu.conf b/local-network/configs/besu/besu.conf index 65846933..a86d6232 100644 --- a/local-network/configs/besu/besu.conf +++ b/local-network/configs/besu/besu.conf @@ -1,8 +1,7 @@ # /opt/besu belongs to besu user: https://github.com/hyperledger/besu/blob/main/docker/openjdk-17/Dockerfile # so it is the only writable path data-path = "/opt/besu/data" -genesis-file = "/genesis.json" -node-private-key-file = "/etc/secrets/p2p-key" +genesis-file = "/etc/secrets/genesis.json" sync-mode = "FULL" host-allowlist = ["*"] diff --git a/local-network/configs/besu/besu.yml b/local-network/configs/besu/besu.yml index e683f057..5d822ccc 100644 --- a/local-network/configs/besu/besu.yml +++ b/local-network/configs/besu/besu.yml @@ -2,7 +2,7 @@ services: besu: image: hyperledger/besu:latest volumes: - - ../ec-common/genesis.json:/genesis.json:ro + - ../ec-common/:/etc/secrets/:ro - .:/config:ro - ./run-besu.sh:/tmp/run.sh:ro env_file: diff --git a/local-network/configs/besu/run-besu.sh b/local-network/configs/besu/run-besu.sh index 36c69169..03076d5f 100755 --- a/local-network/configs/besu/run-besu.sh +++ b/local-network/configs/besu/run-besu.sh @@ -6,7 +6,9 @@ tee /opt/besu/logs/besu.log <&1 | tee /root/logs/init.log + geth init /etc/secrets/genesis.json 2>&1 | tee /root/logs/init.log fi IP_RAW=$(ip -4 addr show dev eth0 | awk '/inet / {print $2}') @@ -29,8 +29,8 @@ geth \ --ws.origins=* \ --authrpc.addr=0.0.0.0 \ --authrpc.vhosts=* \ - --authrpc.jwtsecret=/etc/secrets/jwtsecret \ - --nodekey=/etc/secrets/p2p-key \ + --authrpc.jwtsecret="/etc/secrets/jwt-secret-${NODE_NUMBER}.hex" \ + --nodekey="/etc/secrets/p2p-key-${NODE_NUMBER}.hex" \ --nat="extip:${IP}" \ --netrestrict="${NETWORK}/${PREFIX}" \ --bootnodes="${BESU_BOOTNODES}" \ diff --git a/local-network/docker-compose.yml b/local-network/docker-compose.yml index ca880fbe..b6d34c49 100644 --- a/local-network/docker-compose.yml +++ b/local-network/docker-compose.yml @@ -8,12 +8,13 @@ services: extends: file: ./configs/besu/besu.yml service: besu + environment: + NODE_NUMBER: 1 ports: - "127.0.0.1:18551:8551" # Engine port - doesn't have all APIs - "127.0.0.1:18545:8545" # RPC port, for Metamask e.g. - "127.0.0.1:18546:8546" # WebSocket volumes: - - ./configs/ec-common/p2p-key-1.hex:/etc/secrets/p2p-key:ro - ./logs/ec-1:/opt/besu/logs ec-2: @@ -25,9 +26,9 @@ services: ports: - "127.0.0.1:28551:8551" # Engine port - "127.0.0.1:28545:8545" # RPC port + environment: + NODE_NUMBER: 2 volumes: - - ./configs/ec-common/p2p-key-2.hex:/etc/secrets/p2p-key:ro - - ./configs/ec-common/jwt-secret-2.hex:/etc/secrets/jwtsecret:ro - ./logs/ec-2:/root/logs wavesnode-1: From aa468023d965b6c01d8f35ac8d7ffbbe64009ad2 Mon Sep 17 00:00:00 2001 From: Vyatcheslav Suharnikov Date: Fri, 13 Dec 2024 14:10:29 +0400 Subject: [PATCH 7/9] jwt-secret-file in application.conf --- local-network/configs/besu/besu.conf | 1 + local-network/configs/besu/run-besu.sh | 1 - src/main/resources/application.conf | 5 +++++ 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/local-network/configs/besu/besu.conf b/local-network/configs/besu/besu.conf index a86d6232..1958b04c 100644 --- a/local-network/configs/besu/besu.conf +++ b/local-network/configs/besu/besu.conf @@ -1,3 +1,4 @@ +# See https://besu.hyperledger.org/public-networks/reference/cli/options # /opt/besu belongs to besu user: https://github.com/hyperledger/besu/blob/main/docker/openjdk-17/Dockerfile # so it is the only writable path data-path = "/opt/besu/data" diff --git a/local-network/configs/besu/run-besu.sh b/local-network/configs/besu/run-besu.sh index 03076d5f..289c89d2 100755 --- a/local-network/configs/besu/run-besu.sh +++ b/local-network/configs/besu/run-besu.sh @@ -6,7 +6,6 @@ tee /opt/besu/logs/besu.log < Date: Fri, 13 Dec 2024 16:39:26 +0400 Subject: [PATCH 8/9] Additional accounts and nodes --- local-network/README.md | 31 +++++-- .../configs/ec-common/p2p-key-bootnode.hex | 1 - .../configs/wavesnode/genesis-template.conf | 18 ++++ local-network/deploy/local/network.py | 18 ++++ local-network/docker-compose.yml | 84 +++++++++++++++++-- 5 files changed, 137 insertions(+), 15 deletions(-) delete mode 100644 local-network/configs/ec-common/p2p-key-bootnode.hex diff --git a/local-network/README.md b/local-network/README.md index 8095dd44..e8c07370 100644 --- a/local-network/README.md +++ b/local-network/README.md @@ -10,18 +10,25 @@ You have to build consensus client. Run [./consensus_client-image-build.sh](./consensus_client-image-build.sh) +## How to add additional nodes + +1. Uncomment in [./docker-compose.yml](./docker-compose.yml) +2. Optionally: Enable EL mining for these nodes in [./deploy/local/network.py](./deploy/local/network.py) (see the CL + section). + ## How to start - Run `./all-images-build.sh` after pulling the repository, so docker compose will pull new external images and rebuild the `deploy` image. - Available docker compose contexts: - - BlockScout services: `bs` - - Tests in the end `tests` -- Run [./restart.sh](./restart.sh) - - With selected contexts, for example, `COMPOSE_PROFILES=bs,tests ./restart.sh` - - Or without any context: `./restart.sh` + - BlockScout services: `bs` + - Tests in the end `tests` +- Run [./restart.sh](./restart.sh) + - With selected contexts, for example, `COMPOSE_PROFILES=bs,tests ./restart.sh` + - Or without any context: `./restart.sh` + +To retry failed: -To retry failed: - deploy - run `./deploy-run.sh`. - tests - run `./tests-run.sh`. @@ -39,12 +46,18 @@ See [./deploy](./deploy/). * Node HTTP API Key: `testapi` * CL accounts: see [genesis-template.conf](configs/wavesnode/genesis-template.conf) * EL mining reward accounts: - * Reward account for **Miner 1** (`wavesnode-1`, `besu-1`): + * Reward account for **Miner 1** (`wavesnode-1`, `ec-1`): * Address: `0x7dBcf9c6C3583b76669100f9BE3CaF6d722bc9f9` * Private key: `16962bb06858ec2e4f252b01391196a5e3699329ff0ce1cc185c213a3844b1cf` - * Reward account for **Miner 2** (`wavesnode-2`, `besu-2`): + * Reward account for **Miner 2** (`wavesnode-2`, `ec-2`): * Address: `0xcF0b9E13FDd593f4Ca26D36aFCaA44dd3FDCCbeD` * Private key: `ab49fee4fc326ecbc7abc7f2e5870bf1f86076eb0979c524e20c843f2a73f647` + * Reward account for **Miner 3** (`wavesnode-3`, `ec-3`): + * Address: `0xf1FE6d7bfebead68A8C06cCcee97B61d7DAA0338` + * Private key: `40151189dda26e893252542f1e628f469871f8770bc9cbe3d095419541a01bd0` + * Reward account for **Miner 4** (`wavesnode-4`, `ec-4`): + * Address: `0x10eDdE5dc07eF63E6bb7018758e6fcB5320d8cAa` + * Private key: `716aacab2cb83b57ce399f0d4e625e7a7ab242d3ee1b29858b0866e146be6086` * To see all information, run `npx tsx common-settings-show.ts` from [./deploy](./deploy/) directory. * Ethereum addresses and private keys for `besu` nodes in [config](configs/ec-common/genesis.json): * `fe3b557e8fb62b89f4916b721be55ceb828dbd73`: `8f2a55949038a9610f50fb23b5883af3b4ecb3c3bb792cbcefbd1542c692be63` @@ -96,7 +109,7 @@ For example, we will deploy a `HelloWorld`: 3. Press "Clear activity tab data" button. 2. If you want to deploy a contract via Explorer ("Contracts" tab), make sure you've chosen not a nightly version and it matches [bridge.sol](./deploy/setup/el/bridge.sol). - + # Useful links ## Besu configuration diff --git a/local-network/configs/ec-common/p2p-key-bootnode.hex b/local-network/configs/ec-common/p2p-key-bootnode.hex deleted file mode 100644 index cf2d9f0e..00000000 --- a/local-network/configs/ec-common/p2p-key-bootnode.hex +++ /dev/null @@ -1 +0,0 @@ -dc51ae50601364b0d9354bad516acd16261447f89bde416399fa4ae5f2cbe8ab \ No newline at end of file diff --git a/local-network/configs/wavesnode/genesis-template.conf b/local-network/configs/wavesnode/genesis-template.conf index d0c505d0..e5b415d9 100644 --- a/local-network/configs/wavesnode/genesis-template.conf +++ b/local-network/configs/wavesnode/genesis-template.conf @@ -35,6 +35,24 @@ genesis-generator { # Address: 3FSrRN8X7cDsLyYTScS8Yf8KSwZgJBwf1jU { seed-text = "devnet-2", nonce = 0, amount = 800900102030000 } + # Miner on wavesnode-3 + # Seed text: devnet-3 + # Nonce: 0 + # Seed: HnyGuCEnV1C + # Private key: 6xx38JtyDrCBUox2HZ1F6qPZYcFHnfkYQzHRvs3wyRfH + # Public key: 4rfG6p3Ep2dUr4QqWtJwDvy3ySumMejgTE5sdJLzB756 + # Address: 3Fkh3dNmLS6NQtVbHcrADegwLo9DviBL5Ro + { seed-text = "devnet-3", nonce = 0, amount = 700050007000500 } + + # Miner on wavesnode-4 + # Seed text: devnet-4 + # Nonce: 0 + # Seed: HnyGuCEnV1D + # Private key: 26mAQWx1hKjDgiJHLpgGJnp8GWp23ueHjqy3vDJtCtTz + # Public key: CxeyqUAbsfCWHhQfrTq7g7t7PengjQpDejG5cd7i4Pqa + # Address: 3FXMRA1tPsn8LApkqVEQJgzsVdMBrnnd8vp + { seed-text = "devnet-4", nonce = 0, amount = 600100102030000 } + # Additional addresses # Seed text: devnet rich diff --git a/local-network/deploy/local/network.py b/local-network/deploy/local/network.py index 68723222..e647c410 100644 --- a/local-network/deploy/local/network.py +++ b/local-network/deploy/local/network.py @@ -60,6 +60,24 @@ def cl_miners(self) -> List[Miner]: "0xcf0b9e13fdd593f4ca26d36afcaa44dd3fdccbed" ), ), + # Miner( + # account=pw.Address( + # seed="devnet-3", + # nonce=0, + # ), + # el_reward_address_hex=HexStr( + # "0xf1FE6d7bfebead68A8C06cCcee97B61d7DAA0338" + # ), + # ), + # Miner( + # account=pw.Address( + # seed="devnet-4", + # nonce=0, + # ), + # el_reward_address_hex=HexStr( + # "0x10eDdE5dc07eF63E6bb7018758e6fcB5320d8cAa" + # ), + # ), ] @cached_property diff --git a/local-network/docker-compose.yml b/local-network/docker-compose.yml index b6d34c49..ba364053 100644 --- a/local-network/docker-compose.yml +++ b/local-network/docker-compose.yml @@ -21,15 +21,47 @@ services: container_name: ec-2 hostname: ec-2 extends: - file: ./configs/geth/geth.yml - service: geth + file: ./configs/besu/besu.yml + service: besu ports: - - "127.0.0.1:28551:8551" # Engine port - - "127.0.0.1:28545:8545" # RPC port + - "127.0.0.1:28551:8551" + - "127.0.0.1:28545:8545" + - "127.0.0.1:28546:8546" environment: NODE_NUMBER: 2 volumes: - - ./logs/ec-2:/root/logs + - ./logs/ec-2:/opt/besu/logs + + # Make sure, you have enough RAM to run additional nodes + # ec-3: + # container_name: ec-3 + # hostname: ec-3 + # extends: + # file: ./configs/besu/besu.yml + # service: besu + # environment: + # NODE_NUMBER: 3 + # ports: + # - "127.0.0.1:38551:8551" + # - "127.0.0.1:38545:8545" + # - "127.0.0.1:38546:8546" + # volumes: + # - ./logs/ec-3:/opt/besu/logs + + # Geth is not recommended for now, because of rollback issue + # ec-4: + # container_name: ec-4 + # hostname: ec-4 + # extends: + # file: ./configs/geth/geth.yml + # service: geth + # environment: + # NODE_NUMBER: 4 + # ports: + # - "127.0.0.1:48551:8551" + # - "127.0.0.1:48545:8545" + # volumes: + # - ./logs/ec-4:/root/logs wavesnode-1: container_name: wavesnode-1 @@ -71,6 +103,48 @@ services: update-genesis: condition: service_completed_successfully + # wavesnode-3: + # container_name: wavesnode-3 + # hostname: wavesnode-3 + # extends: + # file: ./configs/wavesnode/wavesnode.yml + # service: wavesnode + # image: ${WAVES_NODE_IMAGE_3:-${WAVES_NODE_IMAGE:-consensus-client:local}} + # ports: + # - "127.0.0.1:36869:6869" + # environment: + # NODE_NUMBER: 3 + # WAVES_WALLET_SEED: HnyGuCEnV1C # devnet-3, addr: 3Fkh3dNmLS6NQtVbHcrADegwLo9DviBL5Ro + # JAVA_OPTS: -Dwaves.miner.enable=no + # volumes: + # - ./logs/wavesnode-3:/var/log/waves + # depends_on: + # ec-3: + # condition: service_healthy + # update-genesis: + # condition: service_completed_successfully + + # wavesnode-4: + # container_name: wavesnode-4 + # hostname: wavesnode-4 + # extends: + # file: ./configs/wavesnode/wavesnode.yml + # service: wavesnode + # image: ${WAVES_NODE_IMAGE_4:-${WAVES_NODE_IMAGE:-consensus-client:local}} + # ports: + # - "127.0.0.1:46869:6869" + # environment: + # NODE_NUMBER: 4 + # WAVES_WALLET_SEED: HnyGuCEnV1D # devnet-4, addr: 3FXMRA1tPsn8LApkqVEQJgzsVdMBrnnd8vp + # JAVA_OPTS: -Dwaves.miner.enable=no + # volumes: + # - ./logs/wavesnode-4:/var/log/waves + # depends_on: + # ec-3: + # condition: service_healthy + # update-genesis: + # condition: service_completed_successfully + update-genesis: container_name: update-genesis image: ${WAVES_NODE_IMAGE:-ghcr.io/wavesplatform/waves:test-gengen} From 2bf10b2d85f5ee57f8aaa80c7f9695f34bfc4689 Mon Sep 17 00:00:00 2001 From: Vyatcheslav Suharnikov Date: Fri, 13 Dec 2024 16:58:10 +0400 Subject: [PATCH 9/9] Fixed integration tests --- .../src/test/scala/units/docker/BesuContainer.scala | 4 ++-- .../src/test/scala/units/docker/GethContainer.scala | 5 ++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/consensus-client-it/src/test/scala/units/docker/BesuContainer.scala b/consensus-client-it/src/test/scala/units/docker/BesuContainer.scala index 61022170..fd2b08c9 100644 --- a/consensus-client-it/src/test/scala/units/docker/BesuContainer.scala +++ b/consensus-client-it/src/test/scala/units/docker/BesuContainer.scala @@ -18,12 +18,12 @@ class BesuContainer(network: NetworkImpl, number: Int, ip: String)(implicit http protected override val container = new GenericContainer(DockerImages.BesuExecutionClient) .withNetwork(network) .withExposedPorts(RpcPort, EnginePort) + .withEnv("NODE_NUMBER", s"$number") .withEnv("LOG4J_CONFIGURATION_FILE", "/config/log4j2.xml") .withEnv("ROOT_LOG_FILE_LEVEL", "TRACE") - .withFileSystemBind(s"$ConfigsDir/ec-common/genesis.json", "/genesis.json", BindMode.READ_ONLY) + .withFileSystemBind(s"$ConfigsDir/ec-common", "/etc/secrets", BindMode.READ_ONLY) .withFileSystemBind(s"$ConfigsDir/besu", "/config", BindMode.READ_ONLY) .withFileSystemBind(s"$ConfigsDir/besu/run-besu.sh", "/tmp/run.sh", BindMode.READ_ONLY) - .withFileSystemBind(s"$ConfigsDir/ec-common/p2p-key-$number.hex", "/etc/secrets/p2p-key", BindMode.READ_ONLY) .withFileSystemBind(s"$logFile", "/opt/besu/logs/besu.log", BindMode.READ_WRITE) .withCreateContainerCmdModifier { cmd => cmd diff --git a/consensus-client-it/src/test/scala/units/docker/GethContainer.scala b/consensus-client-it/src/test/scala/units/docker/GethContainer.scala index 88735ee8..0029e715 100644 --- a/consensus-client-it/src/test/scala/units/docker/GethContainer.scala +++ b/consensus-client-it/src/test/scala/units/docker/GethContainer.scala @@ -21,10 +21,9 @@ class GethContainer(network: NetworkImpl, number: Int, ip: String)(implicit http protected override val container = new GenericContainer(DockerImages.GethExecutionClient) .withNetwork(network) .withExposedPorts(RpcPort, EnginePort) - .withFileSystemBind(s"$ConfigsDir/ec-common/genesis.json", "/tmp/genesis.json", BindMode.READ_ONLY) + .withEnv("NODE_NUMBER", s"$number") + .withFileSystemBind(s"$ConfigsDir/ec-common", "/etc/secrets", BindMode.READ_ONLY) .withFileSystemBind(s"$ConfigsDir/geth/run-geth.sh", "/tmp/run.sh", BindMode.READ_ONLY) - .withFileSystemBind(s"$ConfigsDir/ec-common/p2p-key-$number.hex", "/etc/secrets/p2p-key", BindMode.READ_ONLY) - .withFileSystemBind(s"$ConfigsDir/ec-common/jwt-secret-$number.hex", "/etc/secrets/jwtsecret", BindMode.READ_ONLY) .withFileSystemBind(s"$logFile", "/root/logs/log", BindMode.READ_WRITE) .withCreateContainerCmdModifier { cmd => cmd