mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge branch 'develop-evmcc' into pr-jit
This commit is contained in:
commit
ce9b8f78ab
@ -21,6 +21,7 @@ if(JSONRPC_LS)
|
|||||||
target_link_libraries(testeth web3jsonrpc)
|
target_link_libraries(testeth web3jsonrpc)
|
||||||
endif()
|
endif()
|
||||||
if (EVMJIT)
|
if (EVMJIT)
|
||||||
|
target_link_libraries(testeth evm)
|
||||||
target_link_libraries(testeth evmjit)
|
target_link_libraries(testeth evmjit)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
@ -29,6 +30,7 @@ target_link_libraries(createRandomTest ethcore)
|
|||||||
target_link_libraries(createRandomTest boost_chrono)
|
target_link_libraries(createRandomTest boost_chrono)
|
||||||
target_link_libraries(createRandomTest boost_unit_test_framework)
|
target_link_libraries(createRandomTest boost_unit_test_framework)
|
||||||
if (EVMJIT)
|
if (EVMJIT)
|
||||||
|
target_link_libraries(createRandomTest evm)
|
||||||
target_link_libraries(createRandomTest evmjit)
|
target_link_libraries(createRandomTest evmjit)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
@ -380,6 +380,7 @@ void executeTests(const string& _name, const string& _testPathAppendix, std::fun
|
|||||||
{
|
{
|
||||||
BOOST_ERROR("Failed test with Exception: " << _e.what());
|
BOOST_ERROR("Failed test with Exception: " << _e.what());
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
66
jsonrpc.cpp
66
jsonrpc.cpp
@ -237,7 +237,73 @@ BOOST_AUTO_TEST_CASE(jsonrpc_transact)
|
|||||||
BOOST_CHECK_EQUAL(jsToDecimal(balanceString2), "750000000000000000");
|
BOOST_CHECK_EQUAL(jsToDecimal(balanceString2), "750000000000000000");
|
||||||
BOOST_CHECK_EQUAL(txAmount, balance2);
|
BOOST_CHECK_EQUAL(txAmount, balance2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(simple_contract)
|
||||||
|
{
|
||||||
|
cnote << "Testing jsonrpc contract...";
|
||||||
|
KeyPair kp = KeyPair::create();
|
||||||
|
web3->ethereum()->setAddress(kp.address());
|
||||||
|
jsonrpcServer->setAccounts({kp});
|
||||||
|
|
||||||
|
dev::eth::mine(*(web3->ethereum()), 1);
|
||||||
|
|
||||||
|
char const* sourceCode = "contract test {\n"
|
||||||
|
" function f(uint a) returns(uint d) { return a * 7; }\n"
|
||||||
|
"}\n";
|
||||||
|
|
||||||
|
string compiled = jsonrpcClient->eth_solidity(sourceCode);
|
||||||
|
|
||||||
|
Json::Value create;
|
||||||
|
create["code"] = compiled;
|
||||||
|
string contractAddress = jsonrpcClient->eth_transact(create);
|
||||||
|
dev::eth::mine(*(web3->ethereum()), 1);
|
||||||
|
|
||||||
|
Json::Value call;
|
||||||
|
call["to"] = contractAddress;
|
||||||
|
call["data"] = "0x00000000000000000000000000000000000000000000000000000000000000001";
|
||||||
|
string result = jsonrpcClient->eth_call(call);
|
||||||
|
BOOST_CHECK_EQUAL(result, "0x0000000000000000000000000000000000000000000000000000000000000007");
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(contract_storage)
|
||||||
|
{
|
||||||
|
cnote << "Testing jsonrpc contract storage...";
|
||||||
|
KeyPair kp = KeyPair::create();
|
||||||
|
web3->ethereum()->setAddress(kp.address());
|
||||||
|
jsonrpcServer->setAccounts({kp});
|
||||||
|
|
||||||
|
dev::eth::mine(*(web3->ethereum()), 1);
|
||||||
|
|
||||||
|
char const* sourceCode = R"(
|
||||||
|
contract test {
|
||||||
|
uint hello;
|
||||||
|
function writeHello(uint value) returns(bool d){
|
||||||
|
hello = value;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)";
|
||||||
|
|
||||||
|
string compiled = jsonrpcClient->eth_solidity(sourceCode);
|
||||||
|
|
||||||
|
Json::Value create;
|
||||||
|
create["code"] = compiled;
|
||||||
|
string contractAddress = jsonrpcClient->eth_transact(create);
|
||||||
|
dev::eth::mine(*(web3->ethereum()), 1);
|
||||||
|
|
||||||
|
Json::Value transact;
|
||||||
|
transact["to"] = contractAddress;
|
||||||
|
transact["data"] = "0x00000000000000000000000000000000000000000000000000000000000000003";
|
||||||
|
jsonrpcClient->eth_transact(transact);
|
||||||
|
dev::eth::mine(*(web3->ethereum()), 1);
|
||||||
|
|
||||||
|
Json::Value storage = jsonrpcClient->eth_storageAt(contractAddress);
|
||||||
|
BOOST_CHECK_EQUAL(storage.getMemberNames().size(), 1);
|
||||||
|
for (auto name: storage.getMemberNames())
|
||||||
|
BOOST_CHECK_EQUAL(storage[name].asString(), "0x03");
|
||||||
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_SUITE_END()
|
BOOST_AUTO_TEST_SUITE_END()
|
||||||
BOOST_AUTO_TEST_SUITE_END()
|
BOOST_AUTO_TEST_SUITE_END()
|
||||||
|
|
||||||
|
35
recursiveCreateFiller.json
Normal file
35
recursiveCreateFiller.json
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
{
|
||||||
|
"recursiveCreate": {
|
||||||
|
"env": {
|
||||||
|
"previousHash": "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6",
|
||||||
|
"currentNumber": "0",
|
||||||
|
"currentGasLimit": "10000000",
|
||||||
|
"currentDifficulty": "256",
|
||||||
|
"currentTimestamp": 1,
|
||||||
|
"currentCoinbase": "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba"
|
||||||
|
},
|
||||||
|
"pre": {
|
||||||
|
"095e7baea6a6c7c4c2dfeb977efac326af552d87": {
|
||||||
|
"balance": "20000000",
|
||||||
|
"nonce": 0,
|
||||||
|
"code": "{(CODECOPY 0 0 32)(CREATE 0 0 32)}",
|
||||||
|
"storage": {}
|
||||||
|
},
|
||||||
|
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b": {
|
||||||
|
"balance": "1000000000000000000",
|
||||||
|
"nonce": 0,
|
||||||
|
"code": "",
|
||||||
|
"storage": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"transaction": {
|
||||||
|
"nonce": "0",
|
||||||
|
"gasPrice": "1",
|
||||||
|
"gasLimit": "465224",
|
||||||
|
"to": "095e7baea6a6c7c4c2dfeb977efac326af552d87",
|
||||||
|
"value": "100000",
|
||||||
|
"secretKey": "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
|
||||||
|
"data": ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -128,8 +128,6 @@ BOOST_AUTO_TEST_CASE(different_argument_numbers)
|
|||||||
byte(Instruction::JUMP),
|
byte(Instruction::JUMP),
|
||||||
byte(Instruction::JUMPDEST),
|
byte(Instruction::JUMPDEST),
|
||||||
// stack here: ret e h f(1,2,3)
|
// stack here: ret e h f(1,2,3)
|
||||||
byte(Instruction::DUP2),
|
|
||||||
byte(Instruction::POP),
|
|
||||||
byte(Instruction::SWAP1),
|
byte(Instruction::SWAP1),
|
||||||
// stack here: ret e f(1,2,3) h
|
// stack here: ret e f(1,2,3) h
|
||||||
byte(Instruction::POP),
|
byte(Instruction::POP),
|
||||||
|
@ -32,6 +32,9 @@ using namespace std;
|
|||||||
|
|
||||||
namespace dev
|
namespace dev
|
||||||
{
|
{
|
||||||
|
/// Provider another overload for toBigEndian to encode arguments and return values.
|
||||||
|
inline bytes toBigEndian(bool _value) { return bytes({byte(_value)}); }
|
||||||
|
|
||||||
namespace solidity
|
namespace solidity
|
||||||
{
|
{
|
||||||
namespace test
|
namespace test
|
||||||
@ -137,6 +140,7 @@ private:
|
|||||||
m_output = executive.out().toVector();
|
m_output = executive.out().toVector();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
Address m_contractAddress;
|
Address m_contractAddress;
|
||||||
eth::State m_state;
|
eth::State m_state;
|
||||||
u256 const m_gasPrice = 100 * eth::szabo;
|
u256 const m_gasPrice = 100 * eth::szabo;
|
||||||
@ -496,6 +500,228 @@ BOOST_AUTO_TEST_CASE(state_smoke_test)
|
|||||||
BOOST_CHECK(callContractFunction(0, bytes(1, 0x00)) == toBigEndian(u256(0x3)));
|
BOOST_CHECK(callContractFunction(0, bytes(1, 0x00)) == toBigEndian(u256(0x3)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(simple_mapping)
|
||||||
|
{
|
||||||
|
char const* sourceCode = "contract test {\n"
|
||||||
|
" mapping(uint8 => uint8) table;\n"
|
||||||
|
" function get(uint8 k) returns (uint8 v) {\n"
|
||||||
|
" return table[k];\n"
|
||||||
|
" }\n"
|
||||||
|
" function set(uint8 k, uint8 v) {\n"
|
||||||
|
" table[k] = v;\n"
|
||||||
|
" }\n"
|
||||||
|
"}";
|
||||||
|
compileAndRun(sourceCode);
|
||||||
|
|
||||||
|
BOOST_CHECK(callContractFunction(0, bytes({0x00})) == bytes({0x00}));
|
||||||
|
BOOST_CHECK(callContractFunction(0, bytes({0x01})) == bytes({0x00}));
|
||||||
|
BOOST_CHECK(callContractFunction(0, bytes({0xa7})) == bytes({0x00}));
|
||||||
|
callContractFunction(1, bytes({0x01, 0xa1}));
|
||||||
|
BOOST_CHECK(callContractFunction(0, bytes({0x00})) == bytes({0x00}));
|
||||||
|
BOOST_CHECK(callContractFunction(0, bytes({0x01})) == bytes({0xa1}));
|
||||||
|
BOOST_CHECK(callContractFunction(0, bytes({0xa7})) == bytes({0x00}));
|
||||||
|
callContractFunction(1, bytes({0x00, 0xef}));
|
||||||
|
BOOST_CHECK(callContractFunction(0, bytes({0x00})) == bytes({0xef}));
|
||||||
|
BOOST_CHECK(callContractFunction(0, bytes({0x01})) == bytes({0xa1}));
|
||||||
|
BOOST_CHECK(callContractFunction(0, bytes({0xa7})) == bytes({0x00}));
|
||||||
|
callContractFunction(1, bytes({0x01, 0x05}));
|
||||||
|
BOOST_CHECK(callContractFunction(0, bytes({0x00})) == bytes({0xef}));
|
||||||
|
BOOST_CHECK(callContractFunction(0, bytes({0x01})) == bytes({0x05}));
|
||||||
|
BOOST_CHECK(callContractFunction(0, bytes({0xa7})) == bytes({0x00}));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(mapping_state)
|
||||||
|
{
|
||||||
|
char const* sourceCode = "contract Ballot {\n"
|
||||||
|
" mapping(address => bool) canVote;\n"
|
||||||
|
" mapping(address => uint) voteCount;\n"
|
||||||
|
" mapping(address => bool) voted;\n"
|
||||||
|
" function getVoteCount(address addr) returns (uint retVoteCount) {\n"
|
||||||
|
" return voteCount[addr];\n"
|
||||||
|
" }\n"
|
||||||
|
" function grantVoteRight(address addr) {\n"
|
||||||
|
" canVote[addr] = true;\n"
|
||||||
|
" }\n"
|
||||||
|
" function vote(address voter, address vote) returns (bool success) {\n"
|
||||||
|
" if (!canVote[voter] || voted[voter]) return false;\n"
|
||||||
|
" voted[voter] = true;\n"
|
||||||
|
" voteCount[vote] = voteCount[vote] + 1;\n"
|
||||||
|
" return true;\n"
|
||||||
|
" }\n"
|
||||||
|
"}\n";
|
||||||
|
compileAndRun(sourceCode);
|
||||||
|
class Ballot
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
u256 getVoteCount(u160 _address) { return m_voteCount[_address]; }
|
||||||
|
void grantVoteRight(u160 _address) { m_canVote[_address] = true; }
|
||||||
|
bool vote(u160 _voter, u160 _vote)
|
||||||
|
{
|
||||||
|
if (!m_canVote[_voter] || m_voted[_voter]) return false;
|
||||||
|
m_voted[_voter] = true;
|
||||||
|
m_voteCount[_vote]++;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
map<u160, bool> m_canVote;
|
||||||
|
map<u160, u256> m_voteCount;
|
||||||
|
map<u160, bool> m_voted;
|
||||||
|
} ballot;
|
||||||
|
|
||||||
|
auto getVoteCount = bind(&Ballot::getVoteCount, &ballot, _1);
|
||||||
|
auto grantVoteRight = bind(&Ballot::grantVoteRight, &ballot, _1);
|
||||||
|
auto vote = bind(&Ballot::vote, &ballot, _1, _2);
|
||||||
|
testSolidityAgainstCpp(0, getVoteCount, u160(0));
|
||||||
|
testSolidityAgainstCpp(0, getVoteCount, u160(1));
|
||||||
|
testSolidityAgainstCpp(0, getVoteCount, u160(2));
|
||||||
|
// voting without vote right shourd be rejected
|
||||||
|
testSolidityAgainstCpp(2, vote, u160(0), u160(2));
|
||||||
|
testSolidityAgainstCpp(0, getVoteCount, u160(0));
|
||||||
|
testSolidityAgainstCpp(0, getVoteCount, u160(1));
|
||||||
|
testSolidityAgainstCpp(0, getVoteCount, u160(2));
|
||||||
|
// grant vote rights
|
||||||
|
testSolidityAgainstCpp(1, grantVoteRight, u160(0));
|
||||||
|
testSolidityAgainstCpp(1, grantVoteRight, u160(1));
|
||||||
|
// vote, should increase 2's vote count
|
||||||
|
testSolidityAgainstCpp(2, vote, u160(0), u160(2));
|
||||||
|
testSolidityAgainstCpp(0, getVoteCount, u160(0));
|
||||||
|
testSolidityAgainstCpp(0, getVoteCount, u160(1));
|
||||||
|
testSolidityAgainstCpp(0, getVoteCount, u160(2));
|
||||||
|
// vote again, should be rejected
|
||||||
|
testSolidityAgainstCpp(2, vote, u160(0), u160(1));
|
||||||
|
testSolidityAgainstCpp(0, getVoteCount, u160(0));
|
||||||
|
testSolidityAgainstCpp(0, getVoteCount, u160(1));
|
||||||
|
testSolidityAgainstCpp(0, getVoteCount, u160(2));
|
||||||
|
// vote without right to vote
|
||||||
|
testSolidityAgainstCpp(2, vote, u160(2), u160(1));
|
||||||
|
testSolidityAgainstCpp(0, getVoteCount, u160(0));
|
||||||
|
testSolidityAgainstCpp(0, getVoteCount, u160(1));
|
||||||
|
testSolidityAgainstCpp(0, getVoteCount, u160(2));
|
||||||
|
// grant vote right and now vote again
|
||||||
|
testSolidityAgainstCpp(1, grantVoteRight, u160(2));
|
||||||
|
testSolidityAgainstCpp(2, vote, u160(2), u160(1));
|
||||||
|
testSolidityAgainstCpp(0, getVoteCount, u160(0));
|
||||||
|
testSolidityAgainstCpp(0, getVoteCount, u160(1));
|
||||||
|
testSolidityAgainstCpp(0, getVoteCount, u160(2));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(mapping_state_inc_dec)
|
||||||
|
{
|
||||||
|
char const* sourceCode = "contract test {\n"
|
||||||
|
" uint value;\n"
|
||||||
|
" mapping(uint => uint) table;\n"
|
||||||
|
" function f(uint x) returns (uint y) {\n"
|
||||||
|
" value = x;\n"
|
||||||
|
" if (x > 0) table[++value] = 8;\n"
|
||||||
|
" if (x > 1) value--;\n"
|
||||||
|
" if (x > 2) table[value]++;\n"
|
||||||
|
" return --table[value++];\n"
|
||||||
|
" }\n"
|
||||||
|
"}\n";
|
||||||
|
compileAndRun(sourceCode);
|
||||||
|
|
||||||
|
u256 value = 0;
|
||||||
|
map<u256, u256> table;
|
||||||
|
auto f = [&](u256 const& _x) -> u256
|
||||||
|
{
|
||||||
|
value = _x;
|
||||||
|
if (_x > 0)
|
||||||
|
table[++value] = 8;
|
||||||
|
if (_x > 1)
|
||||||
|
value --;
|
||||||
|
if (_x > 2)
|
||||||
|
table[value]++;
|
||||||
|
return --table[value++];
|
||||||
|
};
|
||||||
|
testSolidityAgainstCppOnRange(0, f, 0, 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(multi_level_mapping)
|
||||||
|
{
|
||||||
|
char const* sourceCode = "contract test {\n"
|
||||||
|
" mapping(uint => mapping(uint => uint)) table;\n"
|
||||||
|
" function f(uint x, uint y, uint z) returns (uint w) {\n"
|
||||||
|
" if (z == 0) return table[x][y];\n"
|
||||||
|
" else return table[x][y] = z;\n"
|
||||||
|
" }\n"
|
||||||
|
"}\n";
|
||||||
|
compileAndRun(sourceCode);
|
||||||
|
|
||||||
|
map<u256, map<u256, u256>> table;
|
||||||
|
auto f = [&](u256 const& _x, u256 const& _y, u256 const& _z) -> u256
|
||||||
|
{
|
||||||
|
if (_z == 0) return table[_x][_y];
|
||||||
|
else return table[_x][_y] = _z;
|
||||||
|
};
|
||||||
|
testSolidityAgainstCpp(0, f, u256(4), u256(5), u256(0));
|
||||||
|
testSolidityAgainstCpp(0, f, u256(5), u256(4), u256(0));
|
||||||
|
testSolidityAgainstCpp(0, f, u256(4), u256(5), u256(9));
|
||||||
|
testSolidityAgainstCpp(0, f, u256(4), u256(5), u256(0));
|
||||||
|
testSolidityAgainstCpp(0, f, u256(5), u256(4), u256(0));
|
||||||
|
testSolidityAgainstCpp(0, f, u256(5), u256(4), u256(7));
|
||||||
|
testSolidityAgainstCpp(0, f, u256(4), u256(5), u256(0));
|
||||||
|
testSolidityAgainstCpp(0, f, u256(5), u256(4), u256(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(structs)
|
||||||
|
{
|
||||||
|
char const* sourceCode = "contract test {\n"
|
||||||
|
" struct s1 {\n"
|
||||||
|
" uint8 x;\n"
|
||||||
|
" bool y;\n"
|
||||||
|
" }\n"
|
||||||
|
" struct s2 {\n"
|
||||||
|
" uint32 z;\n"
|
||||||
|
" s1 s1data;\n"
|
||||||
|
" mapping(uint8 => s2) recursive;\n"
|
||||||
|
" }\n"
|
||||||
|
" s2 data;\n"
|
||||||
|
" function check() returns (bool ok) {\n"
|
||||||
|
" return data.z == 1 && data.s1data.x == 2 && \n"
|
||||||
|
" data.s1data.y == true && \n"
|
||||||
|
" data.recursive[3].recursive[4].z == 5 && \n"
|
||||||
|
" data.recursive[4].recursive[3].z == 6 && \n"
|
||||||
|
" data.recursive[0].s1data.y == false && \n"
|
||||||
|
" data.recursive[4].z == 9;\n"
|
||||||
|
" }\n"
|
||||||
|
" function set() {\n"
|
||||||
|
" data.z = 1;\n"
|
||||||
|
" data.s1data.x = 2;\n"
|
||||||
|
" data.s1data.y = true;\n"
|
||||||
|
" data.recursive[3].recursive[4].z = 5;\n"
|
||||||
|
" data.recursive[4].recursive[3].z = 6;\n"
|
||||||
|
" data.recursive[0].s1data.y = false;\n"
|
||||||
|
" data.recursive[4].z = 9;\n"
|
||||||
|
" }\n"
|
||||||
|
"}\n";
|
||||||
|
compileAndRun(sourceCode);
|
||||||
|
BOOST_CHECK(callContractFunction(0) == bytes({0x00}));
|
||||||
|
BOOST_CHECK(callContractFunction(1) == bytes());
|
||||||
|
BOOST_CHECK(callContractFunction(0) == bytes({0x01}));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(constructor)
|
||||||
|
{
|
||||||
|
char const* sourceCode = "contract test {\n"
|
||||||
|
" mapping(uint => uint) data;\n"
|
||||||
|
" function test() {\n"
|
||||||
|
" data[7] = 8;\n"
|
||||||
|
" }\n"
|
||||||
|
" function get(uint key) returns (uint value) {\n"
|
||||||
|
" return data[key];"
|
||||||
|
" }\n"
|
||||||
|
"}\n";
|
||||||
|
compileAndRun(sourceCode);
|
||||||
|
map<u256, byte> data;
|
||||||
|
data[7] = 8;
|
||||||
|
auto get = [&](u256 const& _x) -> u256
|
||||||
|
{
|
||||||
|
return data[_x];
|
||||||
|
};
|
||||||
|
testSolidityAgainstCpp(0, get, u256(6));
|
||||||
|
testSolidityAgainstCpp(0, get, u256(7));
|
||||||
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_SUITE_END()
|
BOOST_AUTO_TEST_SUITE_END()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -121,6 +121,44 @@ BOOST_AUTO_TEST_CASE(reference_to_later_declaration)
|
|||||||
BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text));
|
BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(struct_definition_directly_recursive)
|
||||||
|
{
|
||||||
|
char const* text = "contract test {\n"
|
||||||
|
" struct MyStructName {\n"
|
||||||
|
" address addr;\n"
|
||||||
|
" MyStructName x;\n"
|
||||||
|
" }\n"
|
||||||
|
"}\n";
|
||||||
|
BOOST_CHECK_THROW(parseTextAndResolveNames(text), ParserError);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(struct_definition_indirectly_recursive)
|
||||||
|
{
|
||||||
|
char const* text = "contract test {\n"
|
||||||
|
" struct MyStructName1 {\n"
|
||||||
|
" address addr;\n"
|
||||||
|
" uint256 count;\n"
|
||||||
|
" MyStructName2 x;\n"
|
||||||
|
" }\n"
|
||||||
|
" struct MyStructName2 {\n"
|
||||||
|
" MyStructName1 x;\n"
|
||||||
|
" }\n"
|
||||||
|
"}\n";
|
||||||
|
BOOST_CHECK_THROW(parseTextAndResolveNames(text), ParserError);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(struct_definition_recursion_via_mapping)
|
||||||
|
{
|
||||||
|
char const* text = "contract test {\n"
|
||||||
|
" struct MyStructName1 {\n"
|
||||||
|
" address addr;\n"
|
||||||
|
" uint256 count;\n"
|
||||||
|
" mapping(uint => MyStructName1) x;\n"
|
||||||
|
" }\n"
|
||||||
|
"}\n";
|
||||||
|
BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text));
|
||||||
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(type_inference_smoke_test)
|
BOOST_AUTO_TEST_CASE(type_inference_smoke_test)
|
||||||
{
|
{
|
||||||
char const* text = "contract test {\n"
|
char const* text = "contract test {\n"
|
||||||
|
34
vm.cpp
34
vm.cpp
@ -306,24 +306,19 @@ void doVMTests(json_spirit::mValue& v, bool _fillin)
|
|||||||
|
|
||||||
auto vm = VMFace::create(vmKind, fev.gas);
|
auto vm = VMFace::create(vmKind, fev.gas);
|
||||||
bytes output;
|
bytes output;
|
||||||
auto outOfGas = false;
|
|
||||||
|
|
||||||
auto startTime = std::chrono::high_resolution_clock::now();
|
auto startTime = std::chrono::high_resolution_clock::now();
|
||||||
u256 gas;
|
u256 gas;
|
||||||
|
bool vmExceptionOccured = false;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
output = vm->go(fev, fev.simpleTrace()).toVector();
|
output = vm->go(fev, fev.simpleTrace()).toVector();
|
||||||
gas = vm->gas();
|
gas = vm->gas();
|
||||||
}
|
}
|
||||||
catch (OutOfGas const&)
|
|
||||||
{
|
|
||||||
outOfGas = true;
|
|
||||||
gas = 0;
|
|
||||||
}
|
|
||||||
catch (VMException const& _e)
|
catch (VMException const& _e)
|
||||||
{
|
{
|
||||||
cnote << "VM did throw an exception: " << diagnostic_information(_e);
|
cnote << "VM did throw an exception: " << diagnostic_information(_e);
|
||||||
gas = 0;
|
vmExceptionOccured = true;
|
||||||
}
|
}
|
||||||
catch (Exception const& _e)
|
catch (Exception const& _e)
|
||||||
{
|
{
|
||||||
@ -370,13 +365,20 @@ void doVMTests(json_spirit::mValue& v, bool _fillin)
|
|||||||
{
|
{
|
||||||
o["env"] = mValue(fev.exportEnv());
|
o["env"] = mValue(fev.exportEnv());
|
||||||
o["exec"] = mValue(fev.exportExec());
|
o["exec"] = mValue(fev.exportExec());
|
||||||
o["post"] = mValue(fev.exportState());
|
if (!vmExceptionOccured)
|
||||||
o["callcreates"] = fev.exportCallCreates();
|
{
|
||||||
o["out"] = "0x" + toHex(output);
|
o["post"] = mValue(fev.exportState());
|
||||||
fev.push(o, "gas", gas);
|
o["callcreates"] = fev.exportCallCreates();
|
||||||
|
o["out"] = "0x" + toHex(output);
|
||||||
|
fev.push(o, "gas", gas);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
if (o.count("post") > 0) // No exceptions expected
|
||||||
|
{
|
||||||
|
BOOST_CHECK(!vmExceptionOccured);
|
||||||
|
|
||||||
BOOST_REQUIRE(o.count("post") > 0);
|
BOOST_REQUIRE(o.count("post") > 0);
|
||||||
BOOST_REQUIRE(o.count("callcreates") > 0);
|
BOOST_REQUIRE(o.count("callcreates") > 0);
|
||||||
BOOST_REQUIRE(o.count("out") > 0);
|
BOOST_REQUIRE(o.count("out") > 0);
|
||||||
@ -388,11 +390,8 @@ void doVMTests(json_spirit::mValue& v, bool _fillin)
|
|||||||
|
|
||||||
checkOutput(output, o);
|
checkOutput(output, o);
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(toInt(o["gas"]), gas);
|
BOOST_CHECK_EQUAL(toInt(o["gas"]), gas);
|
||||||
|
|
||||||
if (outOfGas)
|
|
||||||
BOOST_CHECK_MESSAGE(gas == 0, "Remaining gas not 0 in out-of-gas state");
|
|
||||||
|
|
||||||
auto& expectedAddrs = test.addresses;
|
auto& expectedAddrs = test.addresses;
|
||||||
auto& resultAddrs = fev.addresses;
|
auto& resultAddrs = fev.addresses;
|
||||||
for (auto&& expectedPair : expectedAddrs)
|
for (auto&& expectedPair : expectedAddrs)
|
||||||
@ -416,6 +415,9 @@ void doVMTests(json_spirit::mValue& v, bool _fillin)
|
|||||||
checkAddresses<std::map<Address, std::tuple<u256, u256, std::map<u256, u256>, bytes> > >(test.addresses, fev.addresses);
|
checkAddresses<std::map<Address, std::tuple<u256, u256, std::map<u256, u256>, bytes> > >(test.addresses, fev.addresses);
|
||||||
BOOST_CHECK(test.callcreates == fev.callcreates);
|
BOOST_CHECK(test.callcreates == fev.callcreates);
|
||||||
}
|
}
|
||||||
|
else // Exception expected
|
||||||
|
BOOST_CHECK(vmExceptionOccured);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -179,14 +179,13 @@ p.append(param3);
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string eth_compile(const std::string& param1) throw (jsonrpc::JsonRpcException)
|
Json::Value eth_compilers() throw (jsonrpc::JsonRpcException)
|
||||||
{
|
{
|
||||||
Json::Value p;
|
Json::Value p;
|
||||||
p.append(param1);
|
p = Json::nullValue;
|
||||||
|
Json::Value result = this->client->CallMethod("eth_compilers",p);
|
||||||
Json::Value result = this->client->CallMethod("eth_compile",p);
|
if (result.isArray())
|
||||||
if (result.isString())
|
return result;
|
||||||
return result.asString();
|
|
||||||
else
|
else
|
||||||
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
|
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
|
||||||
|
|
||||||
@ -217,6 +216,19 @@ p.append(param3);
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Json::Value eth_filterLogs(const int& param1) throw (jsonrpc::JsonRpcException)
|
||||||
|
{
|
||||||
|
Json::Value p;
|
||||||
|
p.append(param1);
|
||||||
|
|
||||||
|
Json::Value result = this->client->CallMethod("eth_filterLogs",p);
|
||||||
|
if (result.isArray())
|
||||||
|
return result;
|
||||||
|
else
|
||||||
|
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
std::string eth_gasPrice() throw (jsonrpc::JsonRpcException)
|
std::string eth_gasPrice() throw (jsonrpc::JsonRpcException)
|
||||||
{
|
{
|
||||||
Json::Value p;
|
Json::Value p;
|
||||||
@ -229,19 +241,6 @@ p.append(param3);
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Json::Value eth_getMessages(const int& param1) throw (jsonrpc::JsonRpcException)
|
|
||||||
{
|
|
||||||
Json::Value p;
|
|
||||||
p.append(param1);
|
|
||||||
|
|
||||||
Json::Value result = this->client->CallMethod("eth_getMessages",p);
|
|
||||||
if (result.isArray())
|
|
||||||
return result;
|
|
||||||
else
|
|
||||||
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
bool eth_listening() throw (jsonrpc::JsonRpcException)
|
bool eth_listening() throw (jsonrpc::JsonRpcException)
|
||||||
{
|
{
|
||||||
Json::Value p;
|
Json::Value p;
|
||||||
@ -267,6 +266,19 @@ p.append(param3);
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Json::Value eth_logs(const Json::Value& param1) throw (jsonrpc::JsonRpcException)
|
||||||
|
{
|
||||||
|
Json::Value p;
|
||||||
|
p.append(param1);
|
||||||
|
|
||||||
|
Json::Value result = this->client->CallMethod("eth_logs",p);
|
||||||
|
if (result.isArray())
|
||||||
|
return result;
|
||||||
|
else
|
||||||
|
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
bool eth_mining() throw (jsonrpc::JsonRpcException)
|
bool eth_mining() throw (jsonrpc::JsonRpcException)
|
||||||
{
|
{
|
||||||
Json::Value p;
|
Json::Value p;
|
||||||
@ -329,6 +341,19 @@ p.append(param3);
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string eth_serpent(const std::string& param1) throw (jsonrpc::JsonRpcException)
|
||||||
|
{
|
||||||
|
Json::Value p;
|
||||||
|
p.append(param1);
|
||||||
|
|
||||||
|
Json::Value result = this->client->CallMethod("eth_serpent",p);
|
||||||
|
if (result.isString())
|
||||||
|
return result.asString();
|
||||||
|
else
|
||||||
|
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
bool eth_setCoinbase(const std::string& param1) throw (jsonrpc::JsonRpcException)
|
bool eth_setCoinbase(const std::string& param1) throw (jsonrpc::JsonRpcException)
|
||||||
{
|
{
|
||||||
Json::Value p;
|
Json::Value p;
|
||||||
@ -381,6 +406,19 @@ p.append(param3);
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string eth_solidity(const std::string& param1) throw (jsonrpc::JsonRpcException)
|
||||||
|
{
|
||||||
|
Json::Value p;
|
||||||
|
p.append(param1);
|
||||||
|
|
||||||
|
Json::Value result = this->client->CallMethod("eth_solidity",p);
|
||||||
|
if (result.isString())
|
||||||
|
return result.asString();
|
||||||
|
else
|
||||||
|
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
std::string eth_stateAt(const std::string& param1, const std::string& param2) throw (jsonrpc::JsonRpcException)
|
std::string eth_stateAt(const std::string& param1, const std::string& param2) throw (jsonrpc::JsonRpcException)
|
||||||
{
|
{
|
||||||
Json::Value p;
|
Json::Value p;
|
||||||
@ -395,6 +433,19 @@ p.append(param2);
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Json::Value eth_storageAt(const std::string& param1) throw (jsonrpc::JsonRpcException)
|
||||||
|
{
|
||||||
|
Json::Value p;
|
||||||
|
p.append(param1);
|
||||||
|
|
||||||
|
Json::Value result = this->client->CallMethod("eth_storageAt",p);
|
||||||
|
if (result.isObject())
|
||||||
|
return result;
|
||||||
|
else
|
||||||
|
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
std::string eth_transact(const Json::Value& param1) throw (jsonrpc::JsonRpcException)
|
std::string eth_transact(const Json::Value& param1) throw (jsonrpc::JsonRpcException)
|
||||||
{
|
{
|
||||||
Json::Value p;
|
Json::Value p;
|
||||||
|
Loading…
Reference in New Issue
Block a user