mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge remote-tracking branch 'upstream/develop' into addTests
This commit is contained in:
commit
b9ace5452e
@ -20,6 +20,8 @@
|
||||
* Unit tests for Assembly Items from evmcore/Assembly.h
|
||||
*/
|
||||
|
||||
#if ETH_SOLIDITY
|
||||
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <boost/test/unit_test.hpp>
|
||||
@ -119,3 +121,4 @@ BOOST_AUTO_TEST_SUITE_END()
|
||||
}
|
||||
} // end namespaces
|
||||
|
||||
#endif
|
||||
|
@ -44,9 +44,11 @@ target_link_libraries(testeth ${CURL_LIBRARIES})
|
||||
target_link_libraries(testeth ethereum)
|
||||
target_link_libraries(testeth ethcore)
|
||||
target_link_libraries(testeth secp256k1)
|
||||
if (SOLIDITY)
|
||||
target_link_libraries(testeth solidity)
|
||||
endif ()
|
||||
target_link_libraries(testeth testutils)
|
||||
if (NOT HEADLESS AND NOT JUSTTESTS)
|
||||
if (GUI AND NOT JUSTTESTS)
|
||||
target_link_libraries(testeth webthree)
|
||||
target_link_libraries(testeth natspec)
|
||||
endif()
|
||||
|
@ -120,11 +120,15 @@ BOOST_AUTO_TEST_CASE(blocks)
|
||||
ETH_CHECK_EQUAL(expectedBlockInfoBloom, _blockInfo.logBloom);
|
||||
ETH_CHECK_EQUAL(expectedBlockInfoCoinbase, _blockInfo.coinbaseAddress);
|
||||
ETH_CHECK_EQUAL(expectedBlockInfoDifficulty, _blockInfo.difficulty);
|
||||
ETH_CHECK_EQUAL_COLLECTIONS(expectedBlockInfoExtraData.begin(), expectedBlockInfoExtraData.end(),
|
||||
_blockInfo.extraData.begin(), _blockInfo.extraData.end());
|
||||
ETH_CHECK_EQUAL_COLLECTIONS(
|
||||
expectedBlockInfoExtraData.begin(),
|
||||
expectedBlockInfoExtraData.end(),
|
||||
_blockInfo.extraData.begin(),
|
||||
_blockInfo.extraData.end()
|
||||
);
|
||||
ETH_CHECK_EQUAL(expectedBlockInfoGasLimit, _blockInfo.gasLimit);
|
||||
ETH_CHECK_EQUAL(expectedBlockInfoGasUsed, _blockInfo.gasUsed);
|
||||
ETH_CHECK_EQUAL(expectedBlockInfoHash, _blockInfo.hash);
|
||||
ETH_CHECK_EQUAL(expectedBlockInfoHash, _blockInfo.hash());
|
||||
ETH_CHECK_EQUAL(expectedBlockInfoMixHash, _blockInfo.mixHash);
|
||||
ETH_CHECK_EQUAL(expectedBlockInfoNonce, _blockInfo.nonce);
|
||||
ETH_CHECK_EQUAL(expectedBlockInfoNumber, _blockInfo.number);
|
||||
@ -155,8 +159,12 @@ BOOST_AUTO_TEST_CASE(blocks)
|
||||
u256 expectedTransactionSignatureS = h256(fromHex(_t["s"].asString()));
|
||||
// unsigned expectedTransactionSignatureV = jsToInt(t["v"].asString());
|
||||
|
||||
ETH_CHECK_EQUAL_COLLECTIONS(expectedTransactionData.begin(), expectedTransactionData.end(),
|
||||
_transaction.data().begin(), _transaction.data().end());
|
||||
ETH_CHECK_EQUAL_COLLECTIONS(
|
||||
expectedTransactionData.begin(),
|
||||
expectedTransactionData.end(),
|
||||
_transaction.data().begin(),
|
||||
_transaction.data().end()
|
||||
);
|
||||
ETH_CHECK_EQUAL(expectedTransactionGasLimit, _transaction.gas());
|
||||
ETH_CHECK_EQUAL(expectedTransactionGasPrice, _transaction.gasPrice());
|
||||
ETH_CHECK_EQUAL(expectedTransactionNonce, _transaction.nonce());
|
||||
|
@ -19,6 +19,7 @@
|
||||
* @date 2014
|
||||
* Unit tests for the solidity compiler JSON Interface output.
|
||||
*/
|
||||
#if ETH_SOLIDITY
|
||||
|
||||
#include "TestHelper.h"
|
||||
#include <libsolidity/CompilerStack.h>
|
||||
@ -500,3 +501,5 @@ BOOST_AUTO_TEST_SUITE_END()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -20,6 +20,8 @@
|
||||
* Unit tests for the solidity compiler.
|
||||
*/
|
||||
|
||||
#if ETH_SOLIDITY
|
||||
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <boost/test/unit_test.hpp>
|
||||
@ -192,3 +194,4 @@ BOOST_AUTO_TEST_SUITE_END()
|
||||
}
|
||||
} // end namespaces
|
||||
|
||||
#endif
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
/*
|
||||
This file is part of cpp-ethereum.
|
||||
|
||||
@ -22,6 +21,8 @@
|
||||
* Unit tests for the solidity expression compiler, testing the behaviour of the code.
|
||||
*/
|
||||
|
||||
#if ETH_SOLIDITY
|
||||
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
#include <boost/test/unit_test.hpp>
|
||||
@ -3627,3 +3628,4 @@ BOOST_AUTO_TEST_SUITE_END()
|
||||
}
|
||||
} // end namespaces
|
||||
|
||||
#endif
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
/*
|
||||
This file is part of cpp-ethereum.
|
||||
|
||||
@ -21,6 +20,8 @@
|
||||
* Unit tests for the solidity expression compiler.
|
||||
*/
|
||||
|
||||
#if ETH_SOLIDITY
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <libdevcore/Log.h>
|
||||
@ -491,3 +492,4 @@ BOOST_AUTO_TEST_SUITE_END()
|
||||
}
|
||||
} // end namespaces
|
||||
|
||||
#endif
|
||||
|
@ -20,6 +20,8 @@
|
||||
* Unit tests for generating source interfaces for Solidity contracts.
|
||||
*/
|
||||
|
||||
#if ETH_SOLIDITY
|
||||
|
||||
#include "TestHelper.h"
|
||||
#include <libsolidity/CompilerStack.h>
|
||||
#include <libsolidity/AST.h>
|
||||
@ -147,3 +149,5 @@ BOOST_AUTO_TEST_SUITE_END()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -20,6 +20,8 @@
|
||||
* Unit tests for the name and type resolution of the solidity parser.
|
||||
*/
|
||||
|
||||
#if ETH_SOLIDITY
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <libdevcore/Log.h>
|
||||
@ -1627,3 +1629,4 @@ BOOST_AUTO_TEST_SUITE_END()
|
||||
}
|
||||
} // end namespaces
|
||||
|
||||
#endif
|
||||
|
@ -20,6 +20,8 @@
|
||||
* Unit tests for the solidity compiler JSON Interface output.
|
||||
*/
|
||||
|
||||
#if ETH_SOLIDITY
|
||||
|
||||
#include "TestHelper.h"
|
||||
#include <json/json.h>
|
||||
#include <libsolidity/CompilerStack.h>
|
||||
@ -537,3 +539,5 @@ BOOST_AUTO_TEST_SUITE_END()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
/*
|
||||
This file is part of cpp-ethereum.
|
||||
|
||||
@ -21,6 +20,8 @@
|
||||
* Tests for the Solidity optimizer.
|
||||
*/
|
||||
|
||||
#if ETH_SOLIDITY
|
||||
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
#include <boost/test/unit_test.hpp>
|
||||
@ -573,3 +574,5 @@ BOOST_AUTO_TEST_SUITE_END()
|
||||
}
|
||||
}
|
||||
} // end namespaces
|
||||
|
||||
#endif
|
||||
|
@ -20,6 +20,8 @@
|
||||
* Unit tests for the solidity parser.
|
||||
*/
|
||||
|
||||
#if ETH_SOLIDITY
|
||||
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <libdevcore/Log.h>
|
||||
@ -845,3 +847,4 @@ BOOST_AUTO_TEST_SUITE_END()
|
||||
}
|
||||
} // end namespaces
|
||||
|
||||
#endif
|
||||
|
@ -20,6 +20,8 @@
|
||||
* Unit tests for the solidity scanner.
|
||||
*/
|
||||
|
||||
#if ETH_SOLIDITY
|
||||
|
||||
#include <libsolidity/Scanner.h>
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
@ -286,3 +288,5 @@ BOOST_AUTO_TEST_SUITE_END()
|
||||
}
|
||||
}
|
||||
} // end namespaces
|
||||
|
||||
#endif
|
||||
|
@ -20,6 +20,8 @@
|
||||
* Unit tests for the type system of Solidity.
|
||||
*/
|
||||
|
||||
#if ETH_SOLIDITY
|
||||
|
||||
#include <libsolidity/Types.h>
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
@ -91,3 +93,5 @@ BOOST_AUTO_TEST_SUITE_END()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include <libethereum/Client.h>
|
||||
#include <liblll/Compiler.h>
|
||||
#include <libevm/VMFactory.h>
|
||||
#include "Stats.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace dev::eth;
|
||||
@ -69,7 +70,10 @@ namespace test
|
||||
struct ValueTooLarge: virtual Exception {};
|
||||
bigint const c_max256plus1 = bigint(1) << 256;
|
||||
|
||||
ImportTest::ImportTest(json_spirit::mObject& _o, bool isFiller) : m_statePre(Address(_o["env"].get_obj()["currentCoinbase"].get_str()), OverlayDB(), eth::BaseState::Empty), m_statePost(Address(_o["env"].get_obj()["currentCoinbase"].get_str()), OverlayDB(), eth::BaseState::Empty), m_TestObject(_o)
|
||||
ImportTest::ImportTest(json_spirit::mObject& _o, bool isFiller):
|
||||
m_statePre(OverlayDB(), eth::BaseState::Empty, Address(_o["env"].get_obj()["currentCoinbase"].get_str())),
|
||||
m_statePost(OverlayDB(), eth::BaseState::Empty, Address(_o["env"].get_obj()["currentCoinbase"].get_str())),
|
||||
m_TestObject(_o)
|
||||
{
|
||||
importEnv(_o["env"].get_obj());
|
||||
importState(_o["pre"].get_obj(), m_statePre);
|
||||
@ -91,7 +95,7 @@ void ImportTest::importEnv(json_spirit::mObject& _o)
|
||||
assert(_o.count("currentCoinbase") > 0);
|
||||
assert(_o.count("currentNumber") > 0);
|
||||
|
||||
m_environment.previousBlock.hash = h256(_o["previousHash"].get_str());
|
||||
m_environment.currentBlock.parentHash = h256(_o["previousHash"].get_str());
|
||||
m_environment.currentBlock.number = toInt(_o["currentNumber"]);
|
||||
m_environment.currentBlock.gasLimit = toInt(_o["currentGasLimit"]);
|
||||
m_environment.currentBlock.difficulty = toInt(_o["currentDifficulty"]);
|
||||
@ -431,6 +435,9 @@ void executeTests(const string& _name, const string& _testPathAppendix, std::fun
|
||||
string testPath = getTestPath();
|
||||
testPath += _testPathAppendix;
|
||||
|
||||
if (Options::get().stats)
|
||||
Listener::registerListener(Stats::get());
|
||||
|
||||
if (Options::get().fillTests)
|
||||
{
|
||||
try
|
||||
@ -462,6 +469,7 @@ void executeTests(const string& _name, const string& _testPathAppendix, std::fun
|
||||
string s = asString(dev::contents(testPath + "/" + _name + ".json"));
|
||||
BOOST_REQUIRE_MESSAGE(s.length() > 0, "Contents of " + testPath + "/" + _name + ".json is empty. Have you cloned the 'tests' repo branch develop and set ETHEREUM_TEST_PATH to its path?");
|
||||
json_spirit::read_string(s, v);
|
||||
Listener::notifySuiteStarted(_name);
|
||||
doTests(v, false);
|
||||
}
|
||||
catch (Exception const& _e)
|
||||
@ -535,10 +543,12 @@ Options::Options()
|
||||
vmtrace = true;
|
||||
else if (arg == "--filltests")
|
||||
fillTests = true;
|
||||
else if (arg == "--stats")
|
||||
else if (arg.compare(0, 7, "--stats") == 0)
|
||||
{
|
||||
stats = true;
|
||||
else if (arg == "--stats=full")
|
||||
stats = statsFull = true;
|
||||
if (arg.size() > 7)
|
||||
statsOutFile = arg.substr(8); // skip '=' char
|
||||
}
|
||||
else if (arg == "--performance")
|
||||
performance = true;
|
||||
else if (arg == "--quadratic")
|
||||
@ -586,6 +596,12 @@ void Listener::registerListener(Listener& _listener)
|
||||
g_listener = &_listener;
|
||||
}
|
||||
|
||||
void Listener::notifySuiteStarted(std::string const& _name)
|
||||
{
|
||||
if (g_listener)
|
||||
g_listener->suiteStarted(_name);
|
||||
}
|
||||
|
||||
void Listener::notifyTestStarted(std::string const& _name)
|
||||
{
|
||||
if (g_listener)
|
||||
|
@ -101,7 +101,7 @@ namespace test
|
||||
class ImportTest
|
||||
{
|
||||
public:
|
||||
ImportTest(json_spirit::mObject& _o) : m_statePre(Address(), OverlayDB(), eth::BaseState::Empty), m_statePost(Address(), OverlayDB(), eth::BaseState::Empty), m_TestObject(_o) {}
|
||||
ImportTest(json_spirit::mObject& _o): m_TestObject(_o) {}
|
||||
ImportTest(json_spirit::mObject& _o, bool isFiller);
|
||||
// imports
|
||||
void importEnv(json_spirit::mObject& _o);
|
||||
@ -164,7 +164,7 @@ public:
|
||||
bool vmtrace = false; ///< Create EVM execution tracer // TODO: Link with log verbosity?
|
||||
bool fillTests = false; ///< Create JSON test files from execution results
|
||||
bool stats = false; ///< Execution time stats
|
||||
bool statsFull = false; ///< Output full stats - execution times for every test
|
||||
std::string statsOutFile; ///< Stats output file. "out" for standard output
|
||||
|
||||
/// Test selection
|
||||
/// @{
|
||||
@ -191,10 +191,12 @@ class Listener
|
||||
public:
|
||||
virtual ~Listener() = default;
|
||||
|
||||
virtual void suiteStarted(std::string const&) {}
|
||||
virtual void testStarted(std::string const& _name) = 0;
|
||||
virtual void testFinished() = 0;
|
||||
|
||||
static void registerListener(Listener& _listener);
|
||||
static void notifySuiteStarted(std::string const& _name);
|
||||
static void notifyTestStarted(std::string const& _name);
|
||||
static void notifyTestFinished();
|
||||
|
||||
|
@ -52,7 +52,7 @@ void doBlockchainTests(json_spirit::mValue& _v, bool _fillin)
|
||||
|
||||
BOOST_REQUIRE(o.count("pre"));
|
||||
ImportTest importer(o["pre"].get_obj());
|
||||
State state(biGenesisBlock.coinbaseAddress, OverlayDB(), BaseState::Empty);
|
||||
State state(OverlayDB(), BaseState::Empty, biGenesisBlock.coinbaseAddress);
|
||||
importer.importState(o["pre"].get_obj(), state);
|
||||
o["pre"] = fillJsonWithState(state);
|
||||
state.commit();
|
||||
@ -98,7 +98,7 @@ void doBlockchainTests(json_spirit::mValue& _v, bool _fillin)
|
||||
{
|
||||
mObject tx = txObj.get_obj();
|
||||
importer.importTransaction(tx);
|
||||
if (!txs.attemptImport(importer.m_transaction.rlp()))
|
||||
if (txs.import(importer.m_transaction.rlp()) != ImportResult::Success)
|
||||
cnote << "failed importing transaction\n";
|
||||
}
|
||||
|
||||
@ -623,7 +623,7 @@ void updatePoW(BlockInfo& _bi)
|
||||
ret = pow.mine(_bi, 10000, true, true);
|
||||
Ethash::assignResult(ret.second, _bi);
|
||||
}
|
||||
_bi.hash = _bi.headerHash(WithNonce);
|
||||
_bi.noteDirty();
|
||||
}
|
||||
|
||||
void writeBlockHeaderToJson(mObject& _o, BlockInfo const& _bi)
|
||||
@ -643,7 +643,7 @@ void writeBlockHeaderToJson(mObject& _o, BlockInfo const& _bi)
|
||||
_o["extraData"] ="0x" + toHex(_bi.extraData);
|
||||
_o["mixHash"] = toString(_bi.mixHash);
|
||||
_o["nonce"] = toString(_bi.nonce);
|
||||
_o["hash"] = toString(_bi.hash);
|
||||
_o["hash"] = toString(_bi.hash());
|
||||
}
|
||||
|
||||
RLPStream createFullBlockFromHeader(BlockInfo const& _bi, bytes const& _txs, bytes const& _uncles)
|
||||
|
@ -64,7 +64,7 @@ BOOST_AUTO_TEST_CASE(basic_test)
|
||||
unsigned cacheSize(o["cache_size"].get_int());
|
||||
h256 cacheHash(o["cache_hash"].get_str());
|
||||
BOOST_REQUIRE_EQUAL(Ethasher::get()->params(header).cache_size, cacheSize);
|
||||
BOOST_REQUIRE_EQUAL(sha3(bytesConstRef((byte const*)Ethasher::get()->cache(header), cacheSize)), cacheHash);
|
||||
BOOST_REQUIRE_EQUAL(sha3(bytesConstRef((byte const*)Ethasher::get()->light(header), cacheSize)), cacheHash);
|
||||
|
||||
#if TEST_FULL
|
||||
unsigned fullSize(o["full_size"].get_int());
|
||||
|
@ -19,7 +19,7 @@
|
||||
* @date 2015
|
||||
*/
|
||||
|
||||
#if !ETH_HEADLESS
|
||||
#if ETH_GUI
|
||||
|
||||
#include <boost/test/unit_test.hpp>
|
||||
#include <libdevcore/Log.h>
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
/*
|
||||
This file is part of cpp-ethereum.
|
||||
|
||||
|
@ -31,7 +31,6 @@
|
||||
#include <libethereum/Defaults.h>
|
||||
#include <libevm/VM.h>
|
||||
#include "TestHelper.h"
|
||||
#include "Stats.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace json_spirit;
|
||||
@ -42,9 +41,6 @@ namespace dev { namespace test {
|
||||
|
||||
void doStateTests(json_spirit::mValue& v, bool _fillin)
|
||||
{
|
||||
if (Options::get().stats)
|
||||
Listener::registerListener(Stats::get());
|
||||
|
||||
for (auto& i: v.get_obj())
|
||||
{
|
||||
std::cout << " " << i.first << "\n";
|
||||
@ -254,6 +250,7 @@ BOOST_AUTO_TEST_CASE(stRandom)
|
||||
string s = asString(dev::contents(path.string()));
|
||||
BOOST_REQUIRE_MESSAGE(s.length() > 0, "Content of " + path.string() + " is empty. Have you cloned the 'tests' repo branch develop and set ETHEREUM_TEST_PATH to its path?");
|
||||
json_spirit::read_string(s, v);
|
||||
test::Listener::notifySuiteStarted(path.filename().string());
|
||||
dev::test::doStateTests(v, false);
|
||||
}
|
||||
catch (Exception const& _e)
|
||||
|
@ -58,7 +58,7 @@ BOOST_AUTO_TEST_CASE(Complex)
|
||||
CanonBlockChain bc;
|
||||
cout << bc;
|
||||
|
||||
State s(myMiner.address(), stateDB);
|
||||
State s(stateDB, BaseState::Empty, myMiner.address());
|
||||
cout << s;
|
||||
|
||||
// Sync up - this won't do much until we use the last state.
|
||||
|
9
vm.cpp
9
vm.cpp
@ -25,7 +25,6 @@
|
||||
#include <libethereum/Executive.h>
|
||||
#include <libevm/VMFactory.h>
|
||||
#include "vm.h"
|
||||
#include "Stats.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace json_spirit;
|
||||
@ -97,7 +96,7 @@ void FakeExtVM::push(mArray& a, u256 _v)
|
||||
mObject FakeExtVM::exportEnv()
|
||||
{
|
||||
mObject ret;
|
||||
ret["previousHash"] = toString(previousBlock.hash);
|
||||
ret["previousHash"] = toString(currentBlock.parentHash);
|
||||
push(ret, "currentDifficulty", currentBlock.difficulty);
|
||||
push(ret, "currentTimestamp", currentBlock.timestamp);
|
||||
ret["currentCoinbase"] = toString(currentBlock.coinbaseAddress);
|
||||
@ -116,7 +115,7 @@ void FakeExtVM::importEnv(mObject& _o)
|
||||
assert(_o.count("currentCoinbase") > 0);
|
||||
assert(_o.count("currentNumber") > 0);
|
||||
|
||||
previousBlock.hash = h256(_o["previousHash"].get_str());
|
||||
currentBlock.parentHash = h256(_o["previousHash"].get_str());
|
||||
currentBlock.number = toInt(_o["currentNumber"]);
|
||||
lastHashes = test::lastHashes(currentBlock.number);
|
||||
currentBlock.gasLimit = toInt(_o["currentGasLimit"]);
|
||||
@ -311,9 +310,6 @@ namespace dev { namespace test {
|
||||
|
||||
void doVMTests(json_spirit::mValue& v, bool _fillin)
|
||||
{
|
||||
if (Options::get().stats)
|
||||
Listener::registerListener(Stats::get());
|
||||
|
||||
for (auto& i: v.get_obj())
|
||||
{
|
||||
std::cout << " " << i.first << "\n";
|
||||
@ -549,6 +545,7 @@ BOOST_AUTO_TEST_CASE(vmRandom)
|
||||
string s = asString(dev::contents(path.string()));
|
||||
BOOST_REQUIRE_MESSAGE(s.length() > 0, "Content of " + path.string() + " is empty. Have you cloned the 'tests' repo branch develop and set ETHEREUM_TEST_PATH to its path?");
|
||||
json_spirit::read_string(s, v);
|
||||
test::Listener::notifySuiteStarted(path.filename().string());
|
||||
doVMTests(v, false);
|
||||
}
|
||||
catch (Exception const& _e)
|
||||
|
@ -62,6 +62,16 @@ class WebThreeStubClient : public jsonrpc::Client
|
||||
else
|
||||
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
|
||||
}
|
||||
std::string eth_protocolVersion() throw (jsonrpc::JsonRpcException)
|
||||
{
|
||||
Json::Value p;
|
||||
p = Json::nullValue;
|
||||
Json::Value result = this->CallMethod("eth_protocolVersion",p);
|
||||
if (result.isString())
|
||||
return result.asString();
|
||||
else
|
||||
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
|
||||
}
|
||||
std::string eth_coinbase() throw (jsonrpc::JsonRpcException)
|
||||
{
|
||||
Json::Value p;
|
||||
|
Loading…
Reference in New Issue
Block a user