From d5dcfebf03814512f63259bd569a67b12e4095a5 Mon Sep 17 00:00:00 2001 From: Alberto Sala Date: Tue, 2 Jul 2024 17:58:24 +0200 Subject: [PATCH 1/2] Added new fork for EON 1.5 disabling of backward transfers --- .../horizen/examples/AppForkConfigurator.java | 6 +- ...pForkConfiguratorAllEnabledFromEpoch2.java | 7 +- .../horizen/examples/AppForkConfigurator.java | 2 +- qa/SidechainTestFramework/account/utils.py | 2 + qa/sc_evm_backward_transfer.py | 61 +++++++++++-- .../route/AccountTransactionApiRoute.scala | 87 +++++++++++-------- .../account/fork/Version1_5_0Fork.scala | 23 +++++ .../state/WithdrawalMsgProcessor.scala | 7 ++ .../io/horizen/fork/ForkConfigurator.scala | 4 +- .../state/ContractInteropTestBase.scala | 2 +- .../state/ForgerStakeV2MsgProcessorTest.scala | 2 +- ...ddrOwnershipMsgProcessorMultisigTest.scala | 2 +- .../McAddrOwnershipMsgProcessorTest.scala | 2 +- .../account/state/ProxyMsgProcessorTest.scala | 2 +- ...ithdrawalMsgProcessorIntegrationTest.scala | 53 ++++++++++- .../consensus/ConsensusDataStorageTest.scala | 2 +- ...kConfiguratorWithConsensusParamsFork.scala | 2 +- .../horizen/fork/ForkConfiguratorTest.scala | 8 +- .../horizen/fork/SimpleForkConfigurator.scala | 2 +- .../CertificateSubmitterTest.scala | 2 +- .../java/io/horizen/AppForkConfigurator.java | 2 +- .../java/io/horizen/AppForkConfigurator.java | 2 +- 22 files changed, 215 insertions(+), 67 deletions(-) create mode 100644 sdk/src/main/scala/io/horizen/account/fork/Version1_5_0Fork.scala diff --git a/examples/account/evmapp/src/main/java/io/horizen/examples/AppForkConfigurator.java b/examples/account/evmapp/src/main/java/io/horizen/examples/AppForkConfigurator.java index bd99b89551..9abf70a0d6 100644 --- a/examples/account/evmapp/src/main/java/io/horizen/examples/AppForkConfigurator.java +++ b/examples/account/evmapp/src/main/java/io/horizen/examples/AppForkConfigurator.java @@ -12,7 +12,7 @@ public class AppForkConfigurator extends ForkConfigurator { @Override - public SidechainForkConsensusEpoch fork1activation() { + public SidechainForkConsensusEpoch forkActivation() { return new SidechainForkConsensusEpoch(0, 0, 0); } @@ -77,6 +77,10 @@ public List> getOptiona new Pair<>( new SidechainForkConsensusEpoch(80, 80, 80), new Version1_4_0Fork(true) + ), + new Pair<>( + new SidechainForkConsensusEpoch(90, 90, 90), + new Version1_5_0Fork(true) ) ); } diff --git a/examples/account/evmapp/src/main/java/io/horizen/examples/AppForkConfiguratorAllEnabledFromEpoch2.java b/examples/account/evmapp/src/main/java/io/horizen/examples/AppForkConfiguratorAllEnabledFromEpoch2.java index 6c659eb99b..34962704f3 100644 --- a/examples/account/evmapp/src/main/java/io/horizen/examples/AppForkConfiguratorAllEnabledFromEpoch2.java +++ b/examples/account/evmapp/src/main/java/io/horizen/examples/AppForkConfiguratorAllEnabledFromEpoch2.java @@ -9,7 +9,7 @@ public class AppForkConfiguratorAllEnabledFromEpoch2 extends ForkConfigurator { @Override - public SidechainForkConsensusEpoch fork1activation() { + public SidechainForkConsensusEpoch forkActivation() { return new SidechainForkConsensusEpoch(0, 0, 0); } @@ -60,6 +60,11 @@ public List> getOptiona new SidechainForkConsensusEpoch(2, 2, 2), new Version1_4_0Fork(true) ) + // This is not included because this fork disables backward transfers + /* , new Pair<>( + new SidechainForkConsensusEpoch(2, 2, 2), + new Version1_5_0Fork(true) + )*/ ); } } diff --git a/examples/utxo/simpleapp/src/main/java/io/horizen/examples/AppForkConfigurator.java b/examples/utxo/simpleapp/src/main/java/io/horizen/examples/AppForkConfigurator.java index c6b77f389f..f6fe23430a 100644 --- a/examples/utxo/simpleapp/src/main/java/io/horizen/examples/AppForkConfigurator.java +++ b/examples/utxo/simpleapp/src/main/java/io/horizen/examples/AppForkConfigurator.java @@ -5,7 +5,7 @@ public class AppForkConfigurator extends ForkConfigurator { @Override - public SidechainForkConsensusEpoch fork1activation() { + public SidechainForkConsensusEpoch forkActivation() { return new SidechainForkConsensusEpoch(3, 3, 3); } } diff --git a/qa/SidechainTestFramework/account/utils.py b/qa/SidechainTestFramework/account/utils.py index d06a72468b..3ee1b7860e 100644 --- a/qa/SidechainTestFramework/account/utils.py +++ b/qa/SidechainTestFramework/account/utils.py @@ -56,6 +56,8 @@ def convertZenniesToZen(valueInZennies): VERSION_1_3_FORK_EPOCH = 70 # The activation epoch for features released in v1.4, as coded in the sdk VERSION_1_4_FORK_EPOCH = 80 +# The activation epoch for features released in v1.5, as coded in the sdk +VERSION_1_5_FORK_EPOCH = 90 # Block gas limit BLOCK_GAS_LIMIT = 30000000 diff --git a/qa/sc_evm_backward_transfer.py b/qa/sc_evm_backward_transfer.py index df998abd8b..54a55d86ee 100755 --- a/qa/sc_evm_backward_transfer.py +++ b/qa/sc_evm_backward_transfer.py @@ -2,9 +2,9 @@ import logging import pprint import time -from _decimal import Decimal import base58 +from _decimal import Decimal from eth_abi import decode from eth_utils import add_0x_prefix, encode_hex, event_signature_to_log_topic, remove_0x_prefix @@ -18,7 +18,8 @@ from SidechainTestFramework.account.simple_proxy_contract import SimpleProxyContract from SidechainTestFramework.account.utils import (computeForgedTxFee, convertZenToZennies, convertZenniesToWei, - WITHDRAWAL_REQ_SMART_CONTRACT_ADDRESS, INTEROPERABILITY_FORK_EPOCH) + WITHDRAWAL_REQ_SMART_CONTRACT_ADDRESS, INTEROPERABILITY_FORK_EPOCH, + VERSION_1_5_FORK_EPOCH) from SidechainTestFramework.sc_forging_util import check_mcreference_presence, check_mcreferencedata_presence from SidechainTestFramework.scutil import ( generate_next_block, generate_next_blocks, EVM_APP_SLOT_TIME @@ -60,6 +61,7 @@ and then to MC/SC blocks. - verify epoch 1 certificate, verify backward transfers list - interoperability tests + - Verify that after reaching fork 1.5 backward transfers are disabled, bith via http api and via native contract """ @@ -88,6 +90,18 @@ def __init__(self): super().__init__(block_timestamp_rewind=1500 * EVM_APP_SLOT_TIME * INTEROPERABILITY_FORK_EPOCH, withdrawalEpochLength=10) + def advance_to_epoch(self, epoch_number: int): + sc_node = self.sc_nodes[0] + forging_info = sc_node.block_forgingInfo() + current_epoch = forging_info["result"]["bestBlockEpochNumber"] + # make sure we are not already passed the desired epoch + assert_false(current_epoch > epoch_number, "unexpected epoch number") + while current_epoch < epoch_number: + generate_next_block(sc_node, "first node", force_switch_to_next_epoch=True) + self.sc_sync_all() + forging_info = sc_node.block_forgingInfo() + current_epoch = forging_info["result"]["bestBlockEpochNumber"] + def run_test(self): time.sleep(0.1) @@ -394,8 +408,8 @@ def run_test(self): native_contract = SmartContract("WithdrawalRequests") # Test before interoperability fork - method = "getBackwardTransfers(uint32)" - native_input = format_eoa(native_contract.raw_encode_call(method, current_epoch_number)) + method_get = "getBackwardTransfers(uint32)" + native_input = format_eoa(native_contract.raw_encode_call(method_get, current_epoch_number)) if self.options.all_forks is False: try: proxy_contract.do_static_call(evm_address_interop, 1, WITHDRAWAL_REQ_SMART_CONTRACT_ADDRESS, native_input) @@ -456,8 +470,8 @@ def run_test(self): generate_next_block(sc_node, "first node") # Create a transaction requesting a withdrawal request using the proxy smart contract - method = "backwardTransfer(bytes20)" - native_input = format_eoa(native_contract.raw_encode_call(method, hex_str_to_bytes(mc_address1_pk))) + method_bwt = "backwardTransfer(bytes20)" + native_input = format_eoa(native_contract.raw_encode_call(method_bwt, hex_str_to_bytes(mc_address1_pk))) bt_amount_in_zennies = 100 bt_amount_in_wei = convertZenniesToWei(bt_amount_in_zennies) @@ -512,6 +526,41 @@ def run_test(self): gas_used_tracer = int(trace_result['gasUsed'], 16) assert_true(gas_used == gas_used_tracer, "Wrong gas") + # Create a transaction requesting a withdrawal request via smart contract call + tx_hash = native_contract.call_function(sc_node, method_bwt, hex_str_to_bytes(mc_address1_pk), + fromAddress=evm_address_interop, gasLimit=230000, + toAddress=WITHDRAWAL_REQ_SMART_CONTRACT_ADDRESS, + value=convertZenniesToWei(sc_bt_amount_in_zennies_2)) + + # Check the receipt + tx_receipt = generate_block_and_get_tx_receipt(sc_node, tx_hash)['result'] + assert_equal('0x1', tx_receipt['status'], 'Transaction should fail') + + # try doing the same but reach the fork first, and check we can not do a backward transfer anymore + self.advance_to_epoch(VERSION_1_5_FORK_EPOCH) + + try: + withdrawcoins(sc_node, mc_address2, sc_bt_amount_in_zennies_2) + fail("Interoperability call should fail before fork point") + except Exception as err: + print("Expected exception thrown: {}".format(err)) + # error is raised from API since the address has no balance + assert_true("Fork 1.5 is active" in str(err)) + # 'Something went wrong, see {\'error\': {\'code\': \'0204\', \'description\': \'Fork 1.5 is active, can not invoke this command\', \'detail\': \'\'}}' + + # Create a transaction requesting a withdrawal request using the native smart contract + tx_hash = native_contract.call_function(sc_node, method_bwt, hex_str_to_bytes(mc_address1_pk), + fromAddress=evm_address_interop, gasLimit=230000, + toAddress=WITHDRAWAL_REQ_SMART_CONTRACT_ADDRESS, + value=convertZenniesToWei(sc_bt_amount_in_zennies_2)) + + # Check the receipt + tx_receipt = generate_block_and_get_tx_receipt(sc_node, tx_hash)['result'] + assert_equal('0x0', tx_receipt['status'], 'Transaction should fail') + + res = sc_node.rpc_debug_traceTransaction(tx_hash, {"tracer": "callTracer"})['result'] + assert_true("fork 1.5 active" in str(res['error'])) + if __name__ == "__main__": SCEvmBackwardTransfer().main() diff --git a/sdk/src/main/scala/io/horizen/account/api/http/route/AccountTransactionApiRoute.scala b/sdk/src/main/scala/io/horizen/account/api/http/route/AccountTransactionApiRoute.scala index 4f1747252c..ad52724f74 100644 --- a/sdk/src/main/scala/io/horizen/account/api/http/route/AccountTransactionApiRoute.scala +++ b/sdk/src/main/scala/io/horizen/account/api/http/route/AccountTransactionApiRoute.scala @@ -11,7 +11,7 @@ import io.horizen.account.api.http.route.AccountTransactionRestScheme._ import io.horizen.account.block.{AccountBlock, AccountBlockHeader} import io.horizen.account.chain.AccountFeePaymentsInfo import io.horizen.account.companion.SidechainAccountTransactionsCompanion -import io.horizen.account.fork.{Version1_3_0Fork, Version1_4_0Fork} +import io.horizen.account.fork.{Version1_3_0Fork, Version1_4_0Fork, Version1_5_0Fork} import io.horizen.account.node.{AccountNodeView, NodeAccountHistory, NodeAccountMemoryPool, NodeAccountState} import io.horizen.account.proof.SignatureSecp256k1 import io.horizen.account.proposition.AddressProposition @@ -846,47 +846,58 @@ case class AccountTransactionApiRoute(override val settings: RESTApiSettings, entity(as[ReqWithdrawCoins]) { body => // lock the view and try to create CoreTransaction applyOnNodeView { sidechainNodeView => - val valueInWei = ZenWeiConverter.convertZenniesToWei(body.withdrawalRequest.value) - val gasInfo = body.gasInfo - // default gas related params - val baseFee = sidechainNodeView.getNodeState.getNextBaseFee - var maxPriorityFeePerGas = BigInteger.valueOf(120) - var maxFeePerGas = BigInteger.TWO.multiply(baseFee).add(maxPriorityFeePerGas) - var gasLimit = BigInteger.valueOf(500000) + val accountState = sidechainNodeView.getNodeState + val epochNumber = accountState.getConsensusEpochNumber.getOrElse(0) - if (gasInfo.isDefined) { - maxFeePerGas = gasInfo.get.maxFeePerGas - maxPriorityFeePerGas = gasInfo.get.maxPriorityFeePerGas - gasLimit = gasInfo.get.gasLimit - } + if (Version1_5_0Fork.get(epochNumber).active) { + ApiResponseUtil.toResponse(GenericTransactionError(s"Fork 1.5 is active, can not invoke this command", + JOptional.empty())) + } else { + val valueInWei = ZenWeiConverter.convertZenniesToWei(body.withdrawalRequest.value) + val gasInfo = body.gasInfo - val txCost = valueInWei.add(maxFeePerGas.multiply(gasLimit)) - val secret = getFittingSecret(sidechainNodeView, None, txCost) - secret match { - case Some(secret) => - val dataBytes = encodeAddNewWithdrawalRequestCmd(body.withdrawalRequest) - dataBytes match { - case Success(data) => - val nonce = body.nonce.getOrElse(sidechainNodeView.getNodeState.getNonce(secret.publicImage.address)) - val tmpTx: EthereumTransaction = new EthereumTransaction( - params.chainId, - JOptional.of(new AddressProposition(WithdrawalMsgProcessor.contractAddress)), - nonce, - gasLimit, - maxPriorityFeePerGas, - maxFeePerGas, - valueInWei, - data, - null - ) - validateAndSendTransaction(signTransactionWithSecret(secret, tmpTx)) - case Failure(exc) => - ApiResponseUtil.toResponse(ErrorInvalidMcAddress(s"Invalid Mc address ${body.withdrawalRequest.mainchainAddress}", JOptional.of(exc))) - } - case None => - ApiResponseUtil.toResponse(ErrorInsufficientBalance("No account with enough balance found", JOptional.empty())) + // default gas related params + val baseFee = sidechainNodeView.getNodeState.getNextBaseFee + var maxPriorityFeePerGas = BigInteger.valueOf(120) + var maxFeePerGas = BigInteger.TWO.multiply(baseFee).add(maxPriorityFeePerGas) + var gasLimit = BigInteger.valueOf(500000) + + if (gasInfo.isDefined) { + maxFeePerGas = gasInfo.get.maxFeePerGas + maxPriorityFeePerGas = gasInfo.get.maxPriorityFeePerGas + gasLimit = gasInfo.get.gasLimit + } + + val txCost = valueInWei.add(maxFeePerGas.multiply(gasLimit)) + val secret = getFittingSecret(sidechainNodeView, None, txCost) + secret match { + case Some(secret) => + val dataBytes = encodeAddNewWithdrawalRequestCmd(body.withdrawalRequest) + dataBytes match { + case Success(data) => + val nonce = body.nonce.getOrElse(sidechainNodeView.getNodeState.getNonce(secret.publicImage.address)) + val tmpTx: EthereumTransaction = new EthereumTransaction( + params.chainId, + JOptional.of(new AddressProposition(WithdrawalMsgProcessor.contractAddress)), + nonce, + gasLimit, + maxPriorityFeePerGas, + maxFeePerGas, + valueInWei, + data, + null + ) + validateAndSendTransaction(signTransactionWithSecret(secret, tmpTx)) + case Failure(exc) => + ApiResponseUtil.toResponse(ErrorInvalidMcAddress(s"Invalid Mc address ${body.withdrawalRequest.mainchainAddress}", JOptional.of(exc))) + } + case None => + ApiResponseUtil.toResponse(ErrorInsufficientBalance("No account with enough balance found", JOptional.empty())) + } } + + } } } diff --git a/sdk/src/main/scala/io/horizen/account/fork/Version1_5_0Fork.scala b/sdk/src/main/scala/io/horizen/account/fork/Version1_5_0Fork.scala new file mode 100644 index 0000000000..bd15c28313 --- /dev/null +++ b/sdk/src/main/scala/io/horizen/account/fork/Version1_5_0Fork.scala @@ -0,0 +1,23 @@ +package io.horizen.account.fork + +import io.horizen.fork.{ForkManager, OptionalSidechainFork} + +case class Version1_5_0Fork(active: Boolean = false) extends OptionalSidechainFork + +/** + *

This fork introduces the following major changes:

+ *
    + *
  • 1. It disables the backward transfers submissions as part of the strategy which stops any cross-chain transfer operation between Mainchain and Sidechain with a view to EON2 migration.
  • + *
+ */ +object Version1_5_0Fork { + def get(epochNumber: Int): Version1_5_0Fork = { + ForkManager.getOptionalSidechainFork[Version1_5_0Fork](epochNumber).getOrElse(DefaultFork) + } + + def getActivationEpoch(): Int = { + ForkManager.getFirstActivationEpoch[Version1_5_0Fork]() + } + + private val DefaultFork: Version1_5_0Fork = Version1_5_0Fork() +} diff --git a/sdk/src/main/scala/io/horizen/account/state/WithdrawalMsgProcessor.scala b/sdk/src/main/scala/io/horizen/account/state/WithdrawalMsgProcessor.scala index 4991ee68bc..41f9733122 100644 --- a/sdk/src/main/scala/io/horizen/account/state/WithdrawalMsgProcessor.scala +++ b/sdk/src/main/scala/io/horizen/account/state/WithdrawalMsgProcessor.scala @@ -3,6 +3,7 @@ package io.horizen.account.state import com.google.common.primitives.{Bytes, Ints} import io.horizen.account.abi.ABIUtil.{METHOD_ID_LENGTH, getABIMethodId, getArgumentsFromData, getFunctionSignature} import io.horizen.account.abi.{ABIDecoder, ABIEncodable, ABIListEncoder, MsgProcessorInputDecoder} +import io.horizen.account.fork.Version1_5_0Fork import io.horizen.account.state.events.AddWithdrawalRequest import io.horizen.account.storage.MsgProcessorMetadataStorageReader import io.horizen.account.utils.WellKnownAddresses.WITHDRAWAL_REQ_SMART_CONTRACT_ADDRESS @@ -35,6 +36,10 @@ object WithdrawalMsgProcessor extends NativeSmartContractMsgProcessor with Withd val AddNewWithdrawalReqCmdSig: String = getABIMethodId("backwardTransfer(bytes20)") val DustThresholdInWei: BigInteger = ZenWeiConverter.convertZenniesToWei(ZenCoinsUtils.getMinDustThreshold(ZenCoinsUtils.MC_DEFAULT_FEE_RATE)) + def isForkActive(consensusEpochNumber: Int): Boolean = { + Version1_5_0Fork.get(consensusEpochNumber).active + } + @throws(classOf[ExecutionFailedException]) override def process(invocation: Invocation, view: BaseAccountStateView, metadata: MsgProcessorMetadataStorageReader, context: ExecutionContext): Array[Byte] = { val gasView = view.getGasTrackedView(invocation.gasPool) @@ -43,6 +48,8 @@ object WithdrawalMsgProcessor extends NativeSmartContractMsgProcessor with Withd execGetListOfWithdrawalReqRecords(invocation, gasView) case AddNewWithdrawalReqCmdSig => + if (isForkActive(context.blockContext.consensusEpochNumber)) + throw new ExecutionRevertedException(s"fork 1.5 active, backward transfers disabled") execAddWithdrawalRequest(invocation, gasView, context.blockContext.withdrawalEpochNumber) case functionSig => diff --git a/sdk/src/main/scala/io/horizen/fork/ForkConfigurator.scala b/sdk/src/main/scala/io/horizen/fork/ForkConfigurator.scala index f5eae16a6d..1a786b9705 100644 --- a/sdk/src/main/scala/io/horizen/fork/ForkConfigurator.scala +++ b/sdk/src/main/scala/io/horizen/fork/ForkConfigurator.scala @@ -10,13 +10,13 @@ abstract class ForkConfigurator { /** * Mandatory for every sidechain to provide an epoch number here. */ - val fork1activation: SidechainForkConsensusEpoch + val forkActivation: SidechainForkConsensusEpoch /** * Return the map of configured consensus epoch numbers to mandatory sidechain forks. */ final lazy val mandatorySidechainForks: Map[SidechainForkConsensusEpoch, MandatorySidechainFork] = - MandatorySidechainFork.forks(fork1activation) + MandatorySidechainFork.forks(forkActivation) /** * Return the map of optional sidechain forks and their consensus epoch numbers. diff --git a/sdk/src/test/scala/io/horizen/account/state/ContractInteropTestBase.scala b/sdk/src/test/scala/io/horizen/account/state/ContractInteropTestBase.scala index 0f746a5f03..52bb744367 100644 --- a/sdk/src/test/scala/io/horizen/account/state/ContractInteropTestBase.scala +++ b/sdk/src/test/scala/io/horizen/account/state/ContractInteropTestBase.scala @@ -42,7 +42,7 @@ abstract class ContractInteropTestBase extends MessageProcessorFixture { @Before def setup(): Unit = { class TestOptionalForkConfigurator extends ForkConfigurator { - override val fork1activation: SidechainForkConsensusEpoch = SidechainForkConsensusEpoch(0, 0, 0) + override val forkActivation: SidechainForkConsensusEpoch = SidechainForkConsensusEpoch(0, 0, 0) override def getOptionalSidechainForks: util.List[Pair[SidechainForkConsensusEpoch, OptionalSidechainFork]] = Seq[Pair[SidechainForkConsensusEpoch, OptionalSidechainFork]]( diff --git a/sdk/src/test/scala/io/horizen/account/state/ForgerStakeV2MsgProcessorTest.scala b/sdk/src/test/scala/io/horizen/account/state/ForgerStakeV2MsgProcessorTest.scala index 5722a4c27e..569af8ceae 100644 --- a/sdk/src/test/scala/io/horizen/account/state/ForgerStakeV2MsgProcessorTest.scala +++ b/sdk/src/test/scala/io/horizen/account/state/ForgerStakeV2MsgProcessorTest.scala @@ -128,7 +128,7 @@ class ForgerStakeV2MsgProcessorTest class TestOptionalForkConfigurator extends ForkConfigurator { - override val fork1activation: SidechainForkConsensusEpoch = SidechainForkConsensusEpoch(0, 0, 0) + override val forkActivation: SidechainForkConsensusEpoch = SidechainForkConsensusEpoch(0, 0, 0) override def getOptionalSidechainForks: util.List[Pair[SidechainForkConsensusEpoch, OptionalSidechainFork]] = Seq[Pair[SidechainForkConsensusEpoch, OptionalSidechainFork]]( new Pair(SidechainForkConsensusEpoch(V1_3_MOCK_FORK_POINT, V1_3_MOCK_FORK_POINT, V1_3_MOCK_FORK_POINT), Version1_3_0Fork(true)), diff --git a/sdk/src/test/scala/io/horizen/account/state/McAddrOwnershipMsgProcessorMultisigTest.scala b/sdk/src/test/scala/io/horizen/account/state/McAddrOwnershipMsgProcessorMultisigTest.scala index abf510bf86..6059142056 100644 --- a/sdk/src/test/scala/io/horizen/account/state/McAddrOwnershipMsgProcessorMultisigTest.scala +++ b/sdk/src/test/scala/io/horizen/account/state/McAddrOwnershipMsgProcessorMultisigTest.scala @@ -46,7 +46,7 @@ class McAddrOwnershipMsgProcessorMultisigTest val VER_1_2_MOCK_FORK_POINT: Int = 110 class TestOptionalForkConfigurator extends ForkConfigurator { - override val fork1activation: SidechainForkConsensusEpoch = SidechainForkConsensusEpoch(0, 0, 0) + override val forkActivation: SidechainForkConsensusEpoch = SidechainForkConsensusEpoch(0, 0, 0) override def getOptionalSidechainForks: util.List[Pair[SidechainForkConsensusEpoch, OptionalSidechainFork]] = Seq[Pair[SidechainForkConsensusEpoch, OptionalSidechainFork]]( diff --git a/sdk/src/test/scala/io/horizen/account/state/McAddrOwnershipMsgProcessorTest.scala b/sdk/src/test/scala/io/horizen/account/state/McAddrOwnershipMsgProcessorTest.scala index 5b66a76138..3f1021b79b 100644 --- a/sdk/src/test/scala/io/horizen/account/state/McAddrOwnershipMsgProcessorTest.scala +++ b/sdk/src/test/scala/io/horizen/account/state/McAddrOwnershipMsgProcessorTest.scala @@ -38,7 +38,7 @@ class McAddrOwnershipMsgProcessorTest val ZENDAO_MOCK_FORK_POINT: Int = 100 class TestOptionalForkConfigurator extends ForkConfigurator { - override val fork1activation: SidechainForkConsensusEpoch = SidechainForkConsensusEpoch(0, 0, 0) + override val forkActivation: SidechainForkConsensusEpoch = SidechainForkConsensusEpoch(0, 0, 0) override def getOptionalSidechainForks: util.List[Pair[SidechainForkConsensusEpoch, OptionalSidechainFork]] = Seq[Pair[SidechainForkConsensusEpoch, OptionalSidechainFork]]( diff --git a/sdk/src/test/scala/io/horizen/account/state/ProxyMsgProcessorTest.scala b/sdk/src/test/scala/io/horizen/account/state/ProxyMsgProcessorTest.scala index 0acb63612f..9a87c2a2d1 100644 --- a/sdk/src/test/scala/io/horizen/account/state/ProxyMsgProcessorTest.scala +++ b/sdk/src/test/scala/io/horizen/account/state/ProxyMsgProcessorTest.scala @@ -29,7 +29,7 @@ class ProxyMsgProcessorTest val MOCK_FORK_POINT: Int = 100 class TestOptionalForkConfigurator extends ForkConfigurator { - override val fork1activation: SidechainForkConsensusEpoch = SidechainForkConsensusEpoch(0, 0, 0) + override val forkActivation: SidechainForkConsensusEpoch = SidechainForkConsensusEpoch(0, 0, 0) override def getOptionalSidechainForks: util.List[Pair[SidechainForkConsensusEpoch, OptionalSidechainFork]] = Seq[Pair[SidechainForkConsensusEpoch, OptionalSidechainFork]]( diff --git a/sdk/src/test/scala/io/horizen/account/state/WithdrawalMsgProcessorIntegrationTest.scala b/sdk/src/test/scala/io/horizen/account/state/WithdrawalMsgProcessorIntegrationTest.scala index db07e6d1f1..c95aca7c58 100644 --- a/sdk/src/test/scala/io/horizen/account/state/WithdrawalMsgProcessorIntegrationTest.scala +++ b/sdk/src/test/scala/io/horizen/account/state/WithdrawalMsgProcessorIntegrationTest.scala @@ -2,11 +2,13 @@ package io.horizen.account.state import com.google.common.primitives.Bytes import io.horizen.account.fork.GasFeeFork.DefaultGasFeeFork +import io.horizen.account.fork.Version1_5_0Fork import io.horizen.account.state.events.AddWithdrawalRequest import io.horizen.account.state.receipt.EthereumConsensusDataLog import io.horizen.account.utils.ZenWeiConverter import io.horizen.evm.{Address, Hash} -import io.horizen.utils.{BytesUtils, ClosableResourceHandler} +import io.horizen.fork.{ForkConfigurator, ForkManagerUtil, OptionalSidechainFork, SidechainForkConsensusEpoch} +import io.horizen.utils.{BytesUtils, ClosableResourceHandler, Pair} import org.junit.Assert._ import org.junit._ import org.scalatestplus.junit.JUnitSuite @@ -17,6 +19,7 @@ import sparkz.crypto.hash.Keccak256 import java.math.BigInteger import java.util +import scala.collection.JavaConverters.seqAsJavaListConverter class WithdrawalMsgProcessorIntegrationTest extends JUnitSuite @@ -24,8 +27,21 @@ class WithdrawalMsgProcessorIntegrationTest with WithdrawalMsgProcessorFixture with ClosableResourceHandler { + val V1_5_MOCK_FORK_POINT: Int = 400 + + class TestOptionalForkConfigurator extends ForkConfigurator { + override val forkActivation: SidechainForkConsensusEpoch = SidechainForkConsensusEpoch(0, 0, 0) + + override def getOptionalSidechainForks: util.List[Pair[SidechainForkConsensusEpoch, OptionalSidechainFork]] = + Seq[Pair[SidechainForkConsensusEpoch, OptionalSidechainFork]]( + new Pair(SidechainForkConsensusEpoch(V1_5_MOCK_FORK_POINT, V1_5_MOCK_FORK_POINT, V1_5_MOCK_FORK_POINT), Version1_5_0Fork(true)), + ).asJava + } + @Before - def setUp(): Unit = {} + def setUp(): Unit = { + ForkManagerUtil.initializeForkManager(new TestOptionalForkConfigurator, "regtest") + } @Test def testInit(): Unit = { @@ -110,7 +126,7 @@ class WithdrawalMsgProcessorIntegrationTest getMessage(WithdrawalMsgProcessor.contractAddress, BigInteger.ZERO, data) } val exGetList = intercept[Throwable] { - assertGas(0, badMsgGetList, view, WithdrawalMsgProcessor, defaultBlockContext) + assertGas(0, badMsgGetList, view, WithdrawalMsgProcessor, defaultBlockContext) } assertTrue(exGetList.getMessage.contains("Could not decode")) @@ -191,4 +207,35 @@ class WithdrawalMsgProcessorIntegrationTest assertEquals("Wrong amount in data", expectedEvent.value, listOfDecodedData.get(0)) assertEquals("Wrong epoch number in data", expectedEvent.epochNumber, listOfDecodedData.get(1)) } + + @Test + def testWithdrawalRequestProcessorFork5Activated(): Unit = { + usingView(WithdrawalMsgProcessor) { view => + WithdrawalMsgProcessor.init(view, 0) + + // use a context carrying the info of the epoch number which activates the fork 1.5 + val blockContext = new BlockContext( + Address.ZERO, + 0, + 0, + DefaultGasFeeFork.blockGasLimit, + 0, + V1_5_MOCK_FORK_POINT, + 0, + 1, + MockedHistoryBlockHashProvider, + Hash.ZERO + ) + + // Creating Withdrawal request + val withdrawalAmount = ZenWeiConverter.convertZenniesToWei(123) + val msg = addWithdrawalRequestMessage(withdrawalAmount) + + val ex = intercept[ExecutionRevertedException] { + assertGas(0, msg, view, WithdrawalMsgProcessor, blockContext) + } + assertTrue(ex.getMessage.contains("fork 1.5 active, backward transfers disabled")) + + } + } } diff --git a/sdk/src/test/scala/io/horizen/consensus/ConsensusDataStorageTest.scala b/sdk/src/test/scala/io/horizen/consensus/ConsensusDataStorageTest.scala index 2fe8fc621b..9e6798acbb 100644 --- a/sdk/src/test/scala/io/horizen/consensus/ConsensusDataStorageTest.scala +++ b/sdk/src/test/scala/io/horizen/consensus/ConsensusDataStorageTest.scala @@ -25,7 +25,7 @@ class ConsensusDataStorageTest { @Test def simpleTestAfterFork(): Unit = { - simpleTest(new SimpleForkConfigurator().fork1activation.regtest + 1) + simpleTest(new SimpleForkConfigurator().forkActivation.regtest + 1) } def simpleTest(epochNumber: Int): Unit = { diff --git a/sdk/src/test/scala/io/horizen/fork/CustomForkConfiguratorWithConsensusParamsFork.scala b/sdk/src/test/scala/io/horizen/fork/CustomForkConfiguratorWithConsensusParamsFork.scala index 26923c7d4a..824bbc3a04 100644 --- a/sdk/src/test/scala/io/horizen/fork/CustomForkConfiguratorWithConsensusParamsFork.scala +++ b/sdk/src/test/scala/io/horizen/fork/CustomForkConfiguratorWithConsensusParamsFork.scala @@ -13,7 +13,7 @@ object CustomForkConfiguratorWithConsensusParamsFork { /** * Mandatory for every sidechain to provide an epoch number here. */ - override val fork1activation: SidechainForkConsensusEpoch = SidechainForkConsensusEpoch(10, 20, 0) + override val forkActivation: SidechainForkConsensusEpoch = SidechainForkConsensusEpoch(10, 20, 0) override def getOptionalSidechainForks: util.List[Pair[SidechainForkConsensusEpoch, OptionalSidechainFork]] = { diff --git a/sdk/src/test/scala/io/horizen/fork/ForkConfiguratorTest.scala b/sdk/src/test/scala/io/horizen/fork/ForkConfiguratorTest.scala index f762fa4710..1fa847b1cc 100644 --- a/sdk/src/test/scala/io/horizen/fork/ForkConfiguratorTest.scala +++ b/sdk/src/test/scala/io/horizen/fork/ForkConfiguratorTest.scala @@ -12,14 +12,14 @@ import scala.jdk.CollectionConverters.seqAsJavaListConverter * "Bad" fork because one of the activation epochs is negative, i.e. before the default that activate at 0. */ class BadForkConfigurator extends ForkConfigurator { - override val fork1activation: SidechainForkConsensusEpoch = SidechainForkConsensusEpoch(0, 0, -5) + override val forkActivation: SidechainForkConsensusEpoch = SidechainForkConsensusEpoch(0, 0, -5) } /** * Too many sc2sc forks, only one is allowed. */ class BadSc2scForkConfigurator extends ForkConfigurator { - override val fork1activation: SidechainForkConsensusEpoch = SidechainForkConsensusEpoch(0, 0, 5) + override val forkActivation: SidechainForkConsensusEpoch = SidechainForkConsensusEpoch(0, 0, 5) override def getOptionalSidechainForks: util.List[Pair[SidechainForkConsensusEpoch, OptionalSidechainFork]] = { Seq[Pair[SidechainForkConsensusEpoch, OptionalSidechainFork]]( @@ -49,7 +49,7 @@ case class MustNotDecreaseFork(foo: Long, bar: Long) extends OptionalSidechainFo * Uses the MustNotDecreaseFork and fails its validation (one of the values decreases in a fork). */ class BadOptionalForkConfigurator extends ForkConfigurator { - override val fork1activation: SidechainForkConsensusEpoch = SidechainForkConsensusEpoch(0, 0, 5) + override val forkActivation: SidechainForkConsensusEpoch = SidechainForkConsensusEpoch(0, 0, 5) override def getOptionalSidechainForks: util.List[Pair[SidechainForkConsensusEpoch, OptionalSidechainFork]] = Seq[Pair[SidechainForkConsensusEpoch, OptionalSidechainFork]]( @@ -61,7 +61,7 @@ class BadOptionalForkConfigurator extends ForkConfigurator { } class GoodOptionalForkConfigurator extends ForkConfigurator { - override val fork1activation: SidechainForkConsensusEpoch = SidechainForkConsensusEpoch(0, 0, 5) + override val forkActivation: SidechainForkConsensusEpoch = SidechainForkConsensusEpoch(0, 0, 5) override def getOptionalSidechainForks: util.List[Pair[SidechainForkConsensusEpoch, OptionalSidechainFork]] = Seq[Pair[SidechainForkConsensusEpoch, OptionalSidechainFork]]( diff --git a/sdk/src/test/scala/io/horizen/fork/SimpleForkConfigurator.scala b/sdk/src/test/scala/io/horizen/fork/SimpleForkConfigurator.scala index 4b3342af1d..7ab8e89e8c 100644 --- a/sdk/src/test/scala/io/horizen/fork/SimpleForkConfigurator.scala +++ b/sdk/src/test/scala/io/horizen/fork/SimpleForkConfigurator.scala @@ -1,5 +1,5 @@ package io.horizen.fork class SimpleForkConfigurator extends ForkConfigurator { - override val fork1activation: SidechainForkConsensusEpoch = SidechainForkConsensusEpoch(10, 20, 0) + override val forkActivation: SidechainForkConsensusEpoch = SidechainForkConsensusEpoch(10, 20, 0) } diff --git a/sdk/src/test/scala/io/horizen/utxo/certificatesubmitter/CertificateSubmitterTest.scala b/sdk/src/test/scala/io/horizen/utxo/certificatesubmitter/CertificateSubmitterTest.scala index c3e7d2f446..c3e700495c 100644 --- a/sdk/src/test/scala/io/horizen/utxo/certificatesubmitter/CertificateSubmitterTest.scala +++ b/sdk/src/test/scala/io/horizen/utxo/certificatesubmitter/CertificateSubmitterTest.scala @@ -64,7 +64,7 @@ class CertificateSubmitterTest extends JUnitSuite with MockitoSugar { @Before def init(): Unit = { val forkConfigurator = new SimpleForkConfigurator() - consensusEpochAtWhichForkIsApplied = forkConfigurator.fork1activation.regtest + consensusEpochAtWhichForkIsApplied = forkConfigurator.forkActivation.regtest ForkManagerUtil.initializeForkManager(new SimpleForkConfigurator(), "regtest") } diff --git a/tools/sidechains-sdk-account_sctools/src/main/java/io/horizen/AppForkConfigurator.java b/tools/sidechains-sdk-account_sctools/src/main/java/io/horizen/AppForkConfigurator.java index adbc8b92ad..0c4c9791cf 100644 --- a/tools/sidechains-sdk-account_sctools/src/main/java/io/horizen/AppForkConfigurator.java +++ b/tools/sidechains-sdk-account_sctools/src/main/java/io/horizen/AppForkConfigurator.java @@ -6,7 +6,7 @@ public class AppForkConfigurator extends ForkConfigurator { @Override - public SidechainForkConsensusEpoch fork1activation() { + public SidechainForkConsensusEpoch forkActivation() { return new SidechainForkConsensusEpoch(0, 0, 0); } } diff --git a/tools/sidechains-sdk-utxo_sctools/src/main/java/io/horizen/AppForkConfigurator.java b/tools/sidechains-sdk-utxo_sctools/src/main/java/io/horizen/AppForkConfigurator.java index a28f15c36f..9df9c5a3a1 100644 --- a/tools/sidechains-sdk-utxo_sctools/src/main/java/io/horizen/AppForkConfigurator.java +++ b/tools/sidechains-sdk-utxo_sctools/src/main/java/io/horizen/AppForkConfigurator.java @@ -5,7 +5,7 @@ public class AppForkConfigurator extends ForkConfigurator { @Override - public SidechainForkConsensusEpoch fork1activation() { + public SidechainForkConsensusEpoch forkActivation() { return new SidechainForkConsensusEpoch(0, 0, 0); } } From 98a15ca2b326811ff87f52c5ff24ea7302395214 Mon Sep 17 00:00:00 2001 From: Alberto Sala Date: Wed, 3 Jul 2024 18:56:27 +0200 Subject: [PATCH 2/2] Modifications after code review --- qa/sc_evm_backward_transfer.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/qa/sc_evm_backward_transfer.py b/qa/sc_evm_backward_transfer.py index 54a55d86ee..ddb8bc7091 100755 --- a/qa/sc_evm_backward_transfer.py +++ b/qa/sc_evm_backward_transfer.py @@ -541,10 +541,9 @@ def run_test(self): try: withdrawcoins(sc_node, mc_address2, sc_bt_amount_in_zennies_2) - fail("Interoperability call should fail before fork point") + fail("call should fail after fork 1.5 activation") except Exception as err: print("Expected exception thrown: {}".format(err)) - # error is raised from API since the address has no balance assert_true("Fork 1.5 is active" in str(err)) # 'Something went wrong, see {\'error\': {\'code\': \'0204\', \'description\': \'Fork 1.5 is active, can not invoke this command\', \'detail\': \'\'}}'