-
Notifications
You must be signed in to change notification settings - Fork 401
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
timemarkovqtum
committed
Sep 10, 2024
1 parent
bbc621e
commit 052b98c
Showing
2 changed files
with
149 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,147 @@ | ||
#include <boost/test/unit_test.hpp> | ||
#include <qtumtests/test_utils.h> | ||
#include <qtum/qtumutils.h> | ||
#include <chainparams.h> | ||
|
||
namespace CancunTest{ | ||
|
||
const dev::u256 GASLIMIT = dev::u256(500000); | ||
const dev::h256 HASHTX = dev::h256(ParseHex("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")); | ||
|
||
// Codes used to check that cancun fork | ||
const std::vector<valtype> CODE = { | ||
/* | ||
pragma solidity ^0.8.24; | ||
contract MulService { | ||
function setMultiplier(uint multiplier) external { | ||
assembly { | ||
tstore(0, multiplier) | ||
} | ||
} | ||
function getMultiplier() private view returns (uint multiplier) { | ||
assembly { | ||
multiplier := tload(0) | ||
} | ||
} | ||
function multiply(uint value) external view returns (uint) { | ||
return value * getMultiplier(); | ||
} | ||
} | ||
*/ valtype(ParseHex("6080604052348015600e575f80fd5b506101db8061001c5f395ff3fe608060405234801561000f575f80fd5b5060043610610034575f3560e01c8063641579a614610038578063c6888fa114610054575b5f80fd5b610052600480360381019061004d91906100e4565b610084565b005b61006e600480360381019061006991906100e4565b61008a565b60405161007b919061011e565b60405180910390f35b805f5d50565b5f6100936100a5565b8261009e9190610164565b9050919050565b5f805c905090565b5f80fd5b5f819050919050565b6100c3816100b1565b81146100cd575f80fd5b50565b5f813590506100de816100ba565b92915050565b5f602082840312156100f9576100f86100ad565b5b5f610106848285016100d0565b91505092915050565b610118816100b1565b82525050565b5f6020820190506101315f83018461010f565b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f61016e826100b1565b9150610179836100b1565b9250828202610187816100b1565b9150828204841483151761019e5761019d610137565b5b509291505056fea26469706673582212203dda524f45e82e20c7a5140d36ef2410c23bec4dee31ca21bc368cf508cde0f764736f6c634300081a0033")), | ||
// setMultiplier(5) | ||
valtype(ParseHex("641579a60000000000000000000000000000000000000000000000000000000000000005")), | ||
// multiply(7) | ||
valtype(ParseHex("c6888fa10000000000000000000000000000000000000000000000000000000000000007")), | ||
}; | ||
// Codes IDs used to check that london fork is present | ||
enum class CodeID | ||
{ | ||
mulService = 0, | ||
setMultiplier_5, | ||
multiply_7, | ||
}; | ||
// Get the code identified by the ID | ||
valtype getCode(CodeID id) | ||
{ | ||
return CODE[(int)id]; | ||
} | ||
void genesisLoading(){ | ||
const CChainParams& chainparams = Params(); | ||
int coinbaseMaturity = Params().GetConsensus().CoinbaseMaturity(0); | ||
int forkHeight = coinbaseMaturity + 499; | ||
dev::eth::EVMConsensus evmConsensus; | ||
evmConsensus.QIP6Height = coinbaseMaturity; | ||
evmConsensus.QIP7Height = coinbaseMaturity; | ||
evmConsensus.nMuirGlacierHeight = coinbaseMaturity; | ||
evmConsensus.nLondonHeight = coinbaseMaturity; | ||
evmConsensus.nShanghaiHeight = coinbaseMaturity; | ||
evmConsensus.nCancunHeight = forkHeight; | ||
UpdateCancunHeight(forkHeight); | ||
dev::eth::ChainParams cp(chainparams.EVMGenesisInfo(evmConsensus)); | ||
globalState->populateFrom(cp.genesisState); | ||
globalSealEngine = std::unique_ptr<dev::eth::SealEngineFace>(cp.createSealEngine()); | ||
globalState->db().commit(); | ||
} | ||
void createNewBlocks(TestChain100Setup* testChain100Setup, size_t n){ | ||
std::function<void(size_t n)> generateBlocks = [&](size_t n){ | ||
dev::h256 oldHashStateRoot = globalState->rootHash(); | ||
dev::h256 oldHashUTXORoot = globalState->rootHashUTXO(); | ||
for(size_t i = 0; i < n; i++){ | ||
testChain100Setup->CreateAndProcessBlock({}, GetScriptForRawPubKey(testChain100Setup->coinbaseKey.GetPubKey())); | ||
} | ||
globalState->setRoot(oldHashStateRoot); | ||
globalState->setRootUTXO(oldHashUTXORoot); | ||
}; | ||
generateBlocks(n); | ||
} | ||
BOOST_FIXTURE_TEST_SUITE(cancunfork_tests, TestChain100Setup) | ||
BOOST_AUTO_TEST_CASE(checking_transient_storage_after_fork){ | ||
genesisLoading(); | ||
createNewBlocks(this, 499); | ||
dev::h256 hashTx(HASHTX); | ||
// Create contract | ||
std::vector<QtumTransaction> txs; | ||
txs.push_back(createQtumTransaction(getCode(CodeID::mulService), 0, GASLIMIT, dev::u256(1), ++hashTx, dev::Address())); | ||
auto result = executeBC(txs, *m_node.chainman); | ||
BOOST_CHECK(result.first[0].execRes.excepted == dev::eth::TransactionException::None); | ||
// Create a transaction with 2 outputs that use transient storage. | ||
// The first output set the multiplier to 5. | ||
// The second output multiply the multiplier by 7, and the result is 35. | ||
dev::Address proxy = createQtumAddress(txs[0].getHashWith(), txs[0].getNVout()); | ||
std::vector<QtumTransaction> txCancun; | ||
txCancun.push_back(createQtumTransaction(getCode(CodeID::setMultiplier_5), 0, GASLIMIT, dev::u256(1), ++hashTx, proxy)); | ||
txCancun.push_back(createQtumTransaction(getCode(CodeID::multiply_7), 0, GASLIMIT, dev::u256(1), ++hashTx, proxy)); | ||
result = executeBC(txCancun, *m_node.chainman); | ||
BOOST_CHECK(result.first[0].execRes.excepted == dev::eth::TransactionException::None); | ||
BOOST_CHECK(result.first[1].execRes.excepted == dev::eth::TransactionException::None); | ||
BOOST_CHECK(result.first[0].execRes.gasUsed == 21688); | ||
BOOST_CHECK(result.first[1].execRes.gasUsed == 22179); | ||
BOOST_CHECK(result.first[0].execRes.output.size() == 0); | ||
BOOST_CHECK(result.first[1].execRes.output.size() == 32); | ||
BOOST_CHECK(dev::h256(result.first[1].execRes.output) == dev::h256(35)); | ||
// Create a transaction with an output that use transient storage which is expired. | ||
txCancun.clear(); | ||
txCancun.push_back(createQtumTransaction(getCode(CodeID::multiply_7), 0, GASLIMIT, dev::u256(1), ++hashTx, proxy)); | ||
result = executeBC(txCancun, *m_node.chainman); | ||
BOOST_CHECK(result.first[0].execRes.excepted == dev::eth::TransactionException::None); | ||
BOOST_CHECK(result.first[0].execRes.gasUsed == 22179); | ||
BOOST_CHECK(result.first[0].execRes.output.size() == 32); | ||
BOOST_CHECK(dev::h256(result.first[0].execRes.output) == dev::h256(0)); | ||
} | ||
BOOST_AUTO_TEST_CASE(checking_transient_storage_before_fork){ | ||
genesisLoading(); | ||
createNewBlocks(this, 498); | ||
dev::h256 hashTx(HASHTX); | ||
// Create contract | ||
std::vector<QtumTransaction> txs; | ||
txs.push_back(createQtumTransaction(getCode(CodeID::mulService), 0, GASLIMIT, dev::u256(1), ++hashTx, dev::Address())); | ||
auto result = executeBC(txs, *m_node.chainman); | ||
BOOST_CHECK(result.first[0].execRes.excepted == dev::eth::TransactionException::None); | ||
// Check that tstore and tload are bad instructions | ||
dev::Address proxy = createQtumAddress(txs[0].getHashWith(), txs[0].getNVout()); | ||
std::vector<QtumTransaction> txCancun; | ||
txCancun.push_back(createQtumTransaction(getCode(CodeID::setMultiplier_5), 0, GASLIMIT, dev::u256(1), ++hashTx, proxy)); | ||
txCancun.push_back(createQtumTransaction(getCode(CodeID::multiply_7), 0, GASLIMIT, dev::u256(1), ++hashTx, proxy)); | ||
result = executeBC(txCancun, *m_node.chainman); | ||
BOOST_CHECK(result.first[0].execRes.excepted == dev::eth::TransactionException::BadInstruction); | ||
BOOST_CHECK(result.first[1].execRes.excepted == dev::eth::TransactionException::BadInstruction); | ||
} | ||
BOOST_AUTO_TEST_SUITE_END() | ||
} |