Skip to content

Commit

Permalink
Merge pull request #1036 from HorizenOfficial/st/EON-1856
Browse files Browse the repository at this point in the history
St/eon 1856
  • Loading branch information
paolocappelletti authored May 28, 2024
2 parents 9126509 + 30a3343 commit 5a88a9a
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 7 deletions.
36 changes: 36 additions & 0 deletions qa/sc_evm_test_debug_methods.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
#!/usr/bin/env python3
import logging

from eth_utils import remove_0x_prefix

from SidechainTestFramework.account.ac_chain_setup import AccountChainSetup
from SidechainTestFramework.account.ac_use_smart_contract import SmartContract
from SidechainTestFramework.account.ac_utils import (
contract_function_call, deploy_smart_contract,
generate_block_and_get_tx_receipt,
)
from SidechainTestFramework.account.httpCalls.transaction.createLegacyTransaction import createLegacyTransaction
from test_framework.util import assert_equal, assert_true

"""
Expand All @@ -27,6 +30,7 @@
- Call traceCall method on current block
- Generate a new block without transaction and call tracer methods
- Call traceCall method on pending block
- Test for EON-1856 issue https://horizenlabs.atlassian.net/browse/EON-1856?atlOrigin=eyJpIjoiNDQzNDczZTkyMWVhNGExZTllMjlkNmVjNDkxMDgwNzkiLCJwIjoiaiJ9
"""


Expand Down Expand Up @@ -273,7 +277,39 @@ def run_test(self):
assert_true("output" not in trace_result)
assert_equal("out of gas", trace_result["error"])

# Test for EON-1856 issue.
# Create a transaction and forge a block. This block will have a lower base fee than its parent. The tx is
# created with a max gas fee slightly smaller than the base fee of the parent block but greater than the base
# fee of its block, so it is correctly forged. The test will fail if the debug_trace* methods use the block
# context of the parent block instead of the correct one.

parent_block_base_fee = sc_node.block_best()["result"]['block']['header']['baseFee']

tx_hash = createLegacyTransaction(sc_node,
fromAddress=remove_0x_prefix(self.evm_address),
toAddress=remove_0x_prefix(self.evm_address),
value=1,
gasPrice=parent_block_base_fee - 1
)

tx_status = generate_block_and_get_tx_receipt(sc_node, "0x" + tx_hash, True)
assert_equal(1, tx_status, "Error in tx - unrelated to debug methods")

current_block_base_fee = sc_node.block_best()["result"]['block']['header']['baseFee']
assert_true(current_block_base_fee < parent_block_base_fee, "Test for EON-1856 requires current block "
"base fee {0} is lower than parent block's one {1}"
.format(current_block_base_fee, parent_block_base_fee))

tx_trace = sc_node.rpc_debug_traceTransaction("0x" + tx_hash, {"tracer": "callTracer"})['result']
assert_equal("CALL", tx_trace['type'], "callTracer type not CALL")

block_number = sc_node.rpc_eth_blockNumber()["result"]
tx_trace_block = sc_node.rpc_debug_traceBlockByNumber(block_number, {"tracer": "callTracer"})["result"][0]
assert_equal(tx_trace, tx_trace_block)

block_hash = sc_node.rpc_eth_getBlockByNumber(block_number, False)['result']['hash']
tx_trace_block = sc_node.rpc_debug_traceBlockByHash(block_hash, {"tracer": "callTracer"})["result"][0]
assert_equal(tx_trace, tx_trace_block)


if __name__ == "__main__":
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -873,7 +873,10 @@ class EthService(
val (block, blockInfo) = getBlockById(nodeView, blockId)

// get state at previous block
getStateViewAtTag(nodeView, (blockInfo.height - 1).toString) { (tagStateView, blockContext) =>
getStateViewAtTag(nodeView, (blockInfo.height - 1).toString) { (tagStateView, _) =>
// We don't use the blockContext of the parent block, because it must be the one of block containing the transaction
val blockContext = getBlockContext(block, blockInfo, nodeView.history)

// apply mainchain references
val epochNumber = TimeToEpochUtils.timeStampToEpochNumber(networkParams.sidechainGenesisBlockTimestamp, block.timestamp)
val ftToSmartContractForkActive = Version1_2_0Fork.get(epochNumber).active
Expand Down Expand Up @@ -933,8 +936,14 @@ class EthService(
throw new RpcException(RpcError.fromCode(RpcCode.InvalidParams, s"transaction not found: $transactionHash"))
)


applyOnAccountView { nodeView =>
getStateViewAtTag(nodeView, (blockNumber - 1).toString) { (tagStateView, blockContext) =>
getStateViewAtTag(nodeView, (blockNumber - 1).toString) { (tagStateView, _) =>

// We don't use the blockContext of the parent block, because it must be the one of block containing the transaction
val blockInfo = getBlockInfoById(nodeView, block.id)
val blockContext = getBlockContext(block, blockInfo, nodeView.history)

// apply mainchain references
val epochNumber = TimeToEpochUtils.timeStampToEpochNumber(networkParams.sidechainGenesisBlockTimestamp, block.timestamp)
val ftToSmartContractForkActive = Version1_2_0Fork.get(epochNumber).active
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -461,8 +461,8 @@ class AccountSidechainNodeViewHolderTest extends JUnitSuite
val block5 = generateNextAccountBlock(block4, sidechainTransactionsCompanion, params)
val block6 = generateNextAccountBlock(block5, sidechainTransactionsCompanion, params)

val firstRequestBlocks = Seq(block1, block2, block6)
val secondRequestBlocks = Seq(block3, block4, block5)
val firstRequestBlocks = Seq(block3, block2, block6)
val secondRequestBlocks = Seq(block1, block4, block5)
val correctSequence = Array(block1, block2, block3, block4, block5, block6)
var blockIndex = 0

Expand Down Expand Up @@ -494,6 +494,18 @@ class AccountSidechainNodeViewHolderTest extends JUnitSuite
actorSystem.eventStream.subscribe(eventListener.ref, classOf[ModifiersProcessingResult[AccountBlock]])

mockedNodeViewHolderRef ! ModifiersFromRemote(firstRequestBlocks)
eventListener.fishForMessage(timeout.duration) {
case m =>
m match {
case ModifiersProcessingResult(applied, cleared) => {
assertTrue("Applied block sequence should be empty.", applied.isEmpty)
assertTrue("Cleared block sequence is not empty.", cleared.isEmpty)
true
}
case _ => false // Log
}
}

mockedNodeViewHolderRef ! ModifiersFromRemote(secondRequestBlocks)

eventListener.fishForMessage(timeout.duration) {
Expand Down Expand Up @@ -669,6 +681,16 @@ class AccountSidechainNodeViewHolderTest extends JUnitSuite
actorSystem.eventStream.subscribe(eventListener.ref, classOf[ModifiersProcessingResult[AccountBlock]])

mockedNodeViewHolderRef ! ModifiersFromRemote(halfFullCacheBlocks)
eventListener.fishForMessage(timeout.duration) {
case m =>
m match {
case ModifiersProcessingResult(applied, cleared) =>
assertEquals("Different number of applied blocks", 0, applied.length)
assertEquals("Different number of cleared blocks from cached", 0, cleared.length)
true
case _ => false
}
}
mockedNodeViewHolderRef ! ModifiersFromRemote(twoHundredBlocks)

eventListener.fishForMessage(timeout.duration) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -489,8 +489,8 @@ class SidechainNodeViewHolderTest extends JUnitSuite
val block5 = generateNextSidechainBlock(block4, sidechainTransactionsCompanion, params)
val block6 = generateNextSidechainBlock(block5, sidechainTransactionsCompanion, params)

val firstRequestBlocks = Seq(block1, block2, block6)
val secondRequestBlocks = Seq(block3, block4, block5)
val firstRequestBlocks = Seq(block3, block2, block6)
val secondRequestBlocks = Seq(block1, block4, block5)
val correctSequence = Array(block1, block2, block3, block4, block5, block6)
var blockIndex = 0

Expand Down Expand Up @@ -524,7 +524,7 @@ class SidechainNodeViewHolderTest extends JUnitSuite
case m =>
m match {
case ModifiersProcessingResult(applied, cleared) => {
assertTrue("Applied block sequence is differ", applied.toSet.equals(correctSequence.toSet))
assertEquals("Applied block sequence is differ", correctSequence.toSet, applied.toSet)
assertTrue("Cleared block sequence is not empty.", cleared.isEmpty)
true
}
Expand Down

0 comments on commit 5a88a9a

Please sign in to comment.