Browse Source

Merge branch 'develop' of https://github.com/ethereum/cpp-ethereum into mix_ux

cl-refactor
arkpar 10 years ago
parent
commit
d4125a58a5
  1. 17
      CMakeLists.txt
  2. 16
      CodingStandards.txt
  3. 238
      eth/main.cpp
  4. 2
      libdevcore/Log.cpp
  5. 2
      libdevcore/RLP.cpp
  6. 5
      libdevcore/RLP.h
  7. 12
      libdevcore/Worker.cpp
  8. 6
      libdevcrypto/Common.cpp
  9. 8
      libethereum/BlockChain.cpp
  10. 10
      libethereum/BlockChain.h
  11. 6
      libethereum/Client.cpp
  12. 5
      libethereum/Client.h
  13. 19
      libethereum/ClientBase.cpp
  14. 9
      libethereum/ClientBase.h
  15. 14
      libethereum/Interface.h
  16. 11
      libethereum/State.cpp
  17. 1
      libtestutils/FixedClient.h
  18. 7
      libweb3jsonrpc/WebThreeStubServerBase.cpp
  19. 18
      mix/MixClient.cpp
  20. 13
      mix/MixClient.h
  21. 169
      mix/qml/StateDialog.qml
  22. 4
      mix/qml/StateListModel.qml
  23. 31
      mix/qml/StatusPane.qml
  24. 1
      mix/qml/TransactionDialog.qml
  25. 10
      mix/qml/TransactionLog.qml

17
CMakeLists.txt

@ -15,7 +15,7 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
# Normally, set(...CACHE...) creates cache variables, but does not modify them. # Normally, set(...CACHE...) creates cache variables, but does not modify them.
function(createDefaultCacheConfig) function(createDefaultCacheConfig)
set(VMTRACE OFF CACHE BOOL "VM tracing and run-time checks (useful for cross-implementation VM debugging)") set(VMTRACE OFF CACHE BOOL "VM tracing and run-time checks (useful for cross-implementation VM debugging)")
set(PARANOIA OFF CACHE BOOL "Additional run-time checks") set(PARANOID OFF CACHE BOOL "Additional run-time checks")
set(JSONRPC ON CACHE BOOL "Build with jsonprc. default on") set(JSONRPC ON CACHE BOOL "Build with jsonprc. default on")
set(FATDB OFF CACHE BOOL "Build with ability to list entries in the Trie. Doubles DB size, slows everything down, but good for looking at state diffs and trie contents.") set(FATDB OFF CACHE BOOL "Build with ability to list entries in the Trie. Doubles DB size, slows everything down, but good for looking at state diffs and trie contents.")
set(USENPM OFF CACHE BOOL "Use npm to recompile ethereum.js if it was changed") set(USENPM OFF CACHE BOOL "Use npm to recompile ethereum.js if it was changed")
@ -35,7 +35,7 @@ endfunction()
# propagates CMake configuration options to the compiler # propagates CMake configuration options to the compiler
function(configureProject) function(configureProject)
if (PARANOIA) if (PARANOID)
add_definitions(-DETH_PARANOIA) add_definitions(-DETH_PARANOIA)
endif () endif ()
@ -89,7 +89,7 @@ function(createBuildInfo)
set(ETH_BUILD_PLATFORM "${ETH_BUILD_PLATFORM}/int") set(ETH_BUILD_PLATFORM "${ETH_BUILD_PLATFORM}/int")
endif () endif ()
if (PARANOIA) if (PARANOID)
set(ETH_BUILD_PLATFORM "${ETH_BUILD_PLATFORM}/PARA") set(ETH_BUILD_PLATFORM "${ETH_BUILD_PLATFORM}/PARA")
endif () endif ()
@ -123,9 +123,9 @@ cmake_policy(SET CMP0015 NEW)
# Clear invalid option # Clear invalid option
if ("${CMAKE_BUILD_TYPE}" STREQUAL "Release") if ("${CMAKE_BUILD_TYPE}" STREQUAL "Release")
if (PARANOIA) if (PARANOID)
message("Paranoia requires debug - disabling for release build.") message("Paranoia requires debug - disabling for release build.")
set(PARANOIA OFF) set(PARANOID OFF)
endif () endif ()
if (VMTRACE) if (VMTRACE)
message("VM Tracing requires debug - disabling for release build.") message("VM Tracing requires debug - disabling for release build.")
@ -151,10 +151,10 @@ if (HEADLESS)
set(BUNDLE "minimal") set(BUNDLE "minimal")
endif () endif ()
if (PARANOIA) if (PARANOID)
set(PARANOIA ON) set(PARANOID ON)
else () else ()
set(PARANOIA OFF) set(PARANOID OFF)
endif () endif ()
if (VMTRACE) if (VMTRACE)
set(VMTRACE ON) set(VMTRACE ON)
@ -282,7 +282,6 @@ message("--------------------------------------------------------------- feature
message("-- Chromium support ${ETH_HAVE_WEBENGINE}") message("-- Chromium support ${ETH_HAVE_WEBENGINE}")
message("-- VMTRACE VM execution tracing ${VMTRACE}") message("-- VMTRACE VM execution tracing ${VMTRACE}")
message("-- PROFILING Profiling support ${PROFILING}") message("-- PROFILING Profiling support ${PROFILING}")
message("-- PARANOIA Additional (SLOW) database checking ${PARANOIA}")
message("-- FATDB Full database exploring ${FATDB}") message("-- FATDB Full database exploring ${FATDB}")
message("-- JSONRPC JSON-RPC support ${JSONRPC}") message("-- JSONRPC JSON-RPC support ${JSONRPC}")
message("-- USENPM Javascript source building ${USENPM}") message("-- USENPM Javascript source building ${USENPM}")

16
CodingStandards.txt

@ -113,26 +113,33 @@ d. Favour declarations close to use; don't habitually declare at top of scope al
e. Always pass non-trivial parameters with a const& suffix. e. Always pass non-trivial parameters with a const& suffix.
f. If a function returns multiple values, use std::tuple (std::pair acceptable). Prefer not using */& arguments, except where efficiency requires. f. If a function returns multiple values, use std::tuple (std::pair acceptable). Prefer not using */& arguments, except where efficiency requires.
g. Never use a macro where adequate non-preprocessor C++ can be written. g. Never use a macro where adequate non-preprocessor C++ can be written.
h. Prefer "using NewType = OldType" to "typedef OldType NewType". h. Make use of auto whenever type is clear or unimportant:
i. Make use of auto whenever type is clear or unimportant:
- Always avoid doubly-stating the type. - Always avoid doubly-stating the type.
- Use to avoid vast and unimportant type declarations. - Use to avoid vast and unimportant type declarations.
i. Don't pass bools: prefer enumerations instead.
j. Prefer enum class to straight enum.
(WRONG) (WRONG)
const double d = 0; const double d = 0;
int i, j; int i, j;
char *s; char *s;
float meanAndSigma(std::vector<float> _v, float* _sigma); float meanAndSigma(std::vector<float> _v, float* _sigma, bool _approximate);
Derived* x(dynamic_cast<Derived*>(base)); Derived* x(dynamic_cast<Derived*>(base));
for (map<ComplexTypeOne, ComplexTypeTwo>::iterator i = l.begin(); i != l.end(); ++l) {} for (map<ComplexTypeOne, ComplexTypeTwo>::iterator i = l.begin(); i != l.end(); ++l) {}
(CORRECT) (CORRECT)
enum class Accuracy
{
Approximate,
Exact
};
double const d = 0; double const d = 0;
int i; int i;
int j; int j;
char* s; char* s;
std::tuple<float, float> meanAndSigma(std::vector<float> const& _v); std::tuple<float, float> meanAndSigma(std::vector<float> const& _v, Accuracy _a);
auto x = dynamic_cast<Derived*>(base); auto x = dynamic_cast<Derived*>(base);
for (auto i = x.begin(); i != x.end(); ++i) {} for (auto i = x.begin(); i != x.end(); ++i) {}
@ -192,7 +199,6 @@ c. Where there are exceptions to this (due to excessive use and clear meaning),
d. In general expressions should be roughly as important/semantically meaningful as the space they occupy. d. In general expressions should be roughly as important/semantically meaningful as the space they occupy.
11. Commenting 11. Commenting
a. Comments should be doxygen-compilable, using @notation rather than \notation. a. Comments should be doxygen-compilable, using @notation rather than \notation.

238
eth/main.cpp

@ -115,9 +115,14 @@ void help()
<< " <APPDATA>/Etherum or Library/Application Support/Ethereum)." << endl << " <APPDATA>/Etherum or Library/Application Support/Ethereum)." << endl
<< " -D,--create-dag <this/next/number> Create the DAG in preparation for mining on given block and exit." << endl << " -D,--create-dag <this/next/number> Create the DAG in preparation for mining on given block and exit." << endl
<< " -e,--ether-price <n> Set the ether price in the reference unit e.g. ¢ (Default: 30.679)." << endl << " -e,--ether-price <n> Set the ether price in the reference unit e.g. ¢ (Default: 30.679)." << endl
<< " -E,--export <file> Export file as a concatenated series of blocks and exit." << endl
<< " --from <n> Export only from block n; n may be a decimal, a '0x' prefixed hash, or 'latest'." << endl
<< " --to <n> Export only to block n (inclusive); n may be a decimal, a '0x' prefixed hash, or 'latest'." << endl
<< " --only <n> Equivalent to --export-from n --export-to n." << endl
<< " -f,--force-mining Mine even when there are no transaction to mine (Default: off)" << endl << " -f,--force-mining Mine even when there are no transaction to mine (Default: off)" << endl
<< " -h,--help Show this help message and exit." << endl << " -h,--help Show this help message and exit." << endl
<< " -i,--interactive Enter interactive mode (default: non-interactive)." << endl << " -i,--interactive Enter interactive mode (default: non-interactive)." << endl
<< " -I,--import <file> Import file as a concatenated series of blocks and exit." << endl
#if ETH_JSONRPC #if ETH_JSONRPC
<< " -j,--json-rpc Enable JSON-RPC server (default: off)." << endl << " -j,--json-rpc Enable JSON-RPC server (default: off)." << endl
<< " --json-rpc-port Specify JSON-RPC server port (implies '-j', default: " << SensibleHttpPort << ")." << endl << " --json-rpc-port Specify JSON-RPC server port (implies '-j', default: " << SensibleHttpPort << ")." << endl
@ -209,44 +214,78 @@ void doInitDAG(unsigned _n)
exit(0); exit(0);
} }
static const unsigned NoDAGInit = (unsigned)-3; enum class OperationMode
{
Node,
Import,
Export,
DAGInit
};
enum class Format
{
Binary,
Hex,
Human
};
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
unsigned initDAG = NoDAGInit; // Init defaults
string listenIP; Defaults::get();
unsigned short listenPort = 30303;
string publicIP; /// Operating mode.
string remoteHost; OperationMode mode = OperationMode::Node;
unsigned short remotePort = 30303;
string dbPath; string dbPath;
unsigned mining = ~(unsigned)0;
NodeMode mode = NodeMode::Full; /// File name for import/export.
unsigned peers = 5; string filename;
int miners = -1;
/// Hashes/numbers for export range.
string exportFrom = "1";
string exportTo = "latest";
Format exportFormat = Format::Binary;
/// DAG initialisation param.
unsigned initDAG = 0;
/// General params for Node operation
NodeMode nodeMode = NodeMode::Full;
bool interactive = false; bool interactive = false;
#if ETH_JSONRPC #if ETH_JSONRPC
int jsonrpc = -1; int jsonrpc = -1;
#endif #endif
bool bootstrap = false;
bool upnp = true; bool upnp = true;
bool forceMining = false;
WithExisting killChain = WithExisting::Trust; WithExisting killChain = WithExisting::Trust;
bool jit = false; bool jit = false;
/// Networking params.
string clientName;
string listenIP;
unsigned short listenPort = 30303;
string publicIP;
string remoteHost;
unsigned short remotePort = 30303;
unsigned peers = 5;
bool bootstrap = false;
/// Mining params
unsigned mining = ~(unsigned)0;
int miners = -1;
bool forceMining = false;
bool turboMining = false;
KeyPair us = KeyPair::create();
Address coinbase = us.address();
/// Structured logging params
bool structuredLogging = false; bool structuredLogging = false;
string structuredLoggingFormat = "%Y-%m-%dT%H:%M:%S"; string structuredLoggingFormat = "%Y-%m-%dT%H:%M:%S";
string clientName;
/// Transaction params
TransactionPriority priority = TransactionPriority::Medium; TransactionPriority priority = TransactionPriority::Medium;
double etherPrice = 30.679; double etherPrice = 30.679;
double blockFees = 15.0; double blockFees = 15.0;
// Init defaults
Defaults::get();
// Our address.
KeyPair us = KeyPair::create();
Address coinbase = us.address();
string configFile = getDataDir() + "/config.rlp"; string configFile = getDataDir() + "/config.rlp";
bytes b = contents(configFile); bytes b = contents(configFile);
if (b.size()) if (b.size())
@ -255,12 +294,6 @@ int main(int argc, char** argv)
us = KeyPair(config[0].toHash<Secret>()); us = KeyPair(config[0].toHash<Secret>());
coinbase = config[1].toHash<Address>(); coinbase = config[1].toHash<Address>();
} }
else
{
RLPStream config(2);
config << us.secret() << coinbase;
writeFile(configFile, config.out());
}
for (int i = 1; i < argc; ++i) for (int i = 1; i < argc; ++i)
{ {
@ -275,6 +308,37 @@ int main(int argc, char** argv)
remoteHost = argv[++i]; remoteHost = argv[++i];
else if ((arg == "-p" || arg == "--port") && i + 1 < argc) else if ((arg == "-p" || arg == "--port") && i + 1 < argc)
remotePort = (short)atoi(argv[++i]); remotePort = (short)atoi(argv[++i]);
else if ((arg == "-I" || arg == "--import") && i + 1 < argc)
{
mode = OperationMode::Import;
filename = argv[++i];
}
else if ((arg == "-E" || arg == "--export") && i + 1 < argc)
{
mode = OperationMode::Export;
filename = argv[++i];
}
else if (arg == "--format" && i + 1 < argc)
{
string m = argv[++i];
if (m == "binary")
exportFormat = Format::Binary;
else if (m == "hex")
exportFormat = Format::Hex;
else if (m == "human")
exportFormat = Format::Human;
else
{
cerr << "Bad " << arg << " option: " << m << endl;
return -1;
}
}
else if (arg == "--to" && i + 1 < argc)
exportTo = argv[++i];
else if (arg == "--from" && i + 1 < argc)
exportFrom = argv[++i];
else if (arg == "--only" && i + 1 < argc)
exportTo = exportFrom = argv[++i];
else if ((arg == "-n" || arg == "--upnp") && i + 1 < argc) else if ((arg == "-n" || arg == "--upnp") && i + 1 < argc)
{ {
string m = argv[++i]; string m = argv[++i];
@ -284,7 +348,7 @@ int main(int argc, char** argv)
upnp = false; upnp = false;
else else
{ {
cerr << "Invalid -n/--upnp option: " << m << endl; cerr << "Bad " << arg << " option: " << m << endl;
return -1; return -1;
} }
} }
@ -301,14 +365,13 @@ int main(int argc, char** argv)
} }
catch (BadHexCharacter& _e) catch (BadHexCharacter& _e)
{ {
cwarn << "invalid hex character, coinbase rejected"; cerr << "Bad hex in " << arg << " option: " << argv[i] << endl;
cwarn << boost::diagnostic_information(_e); return -1;
break;
} }
catch (...) catch (...)
{ {
cwarn << "coinbase rejected"; cerr << "Bad " << arg << " option: " << argv[i] << endl;
break; return -1;
} }
else if ((arg == "-s" || arg == "--secret") && i + 1 < argc) else if ((arg == "-s" || arg == "--secret") && i + 1 < argc)
us = KeyPair(h256(fromHex(argv[++i]))); us = KeyPair(h256(fromHex(argv[++i])));
@ -321,6 +384,7 @@ int main(int argc, char** argv)
else if ((arg == "-D" || arg == "--create-dag") && i + 1 < argc) else if ((arg == "-D" || arg == "--create-dag") && i + 1 < argc)
{ {
string m = boost::to_lower_copy(string(argv[++i])); string m = boost::to_lower_copy(string(argv[++i]));
mode = OperationMode::DAGInit;
if (m == "next") if (m == "next")
initDAG = PendingBlock; initDAG = PendingBlock;
else if (m == "this") else if (m == "this")
@ -402,6 +466,8 @@ int main(int argc, char** argv)
bootstrap = true; bootstrap = true;
else if (arg == "-f" || arg == "--force-mining") else if (arg == "-f" || arg == "--force-mining")
forceMining = true; forceMining = true;
else if (arg == "-T" || arg == "--turbo-mining")
turboMining = true;
else if (arg == "-i" || arg == "--interactive") else if (arg == "-i" || arg == "--interactive")
interactive = true; interactive = true;
#if ETH_JSONRPC #if ETH_JSONRPC
@ -420,9 +486,9 @@ int main(int argc, char** argv)
{ {
string m = argv[++i]; string m = argv[++i];
if (m == "full") if (m == "full")
mode = NodeMode::Full; nodeMode = NodeMode::Full;
else if (m == "peer") else if (m == "peer")
mode = NodeMode::PeerServer; nodeMode = NodeMode::PeerServer;
else else
{ {
cerr << "Unknown mode: " << m << endl; cerr << "Unknown mode: " << m << endl;
@ -449,17 +515,20 @@ int main(int argc, char** argv)
} }
} }
{
RLPStream config(2);
config << us.secret() << coinbase;
writeFile(configFile, config.out());
}
// Two codepaths is necessary since named block require database, but numbered // Two codepaths is necessary since named block require database, but numbered
// blocks are superuseful to have when database is already open in another process. // blocks are superuseful to have when database is already open in another process.
if (initDAG < NoDAGInit) if (mode == OperationMode::DAGInit && !(initDAG == LatestBlock || initDAG == PendingBlock))
doInitDAG(initDAG); doInitDAG(initDAG);
if (!clientName.empty()) if (!clientName.empty())
clientName += "/"; clientName += "/";
cout << credits();
StructuredLogger::get().initialize(structuredLogging, structuredLoggingFormat); StructuredLogger::get().initialize(structuredLogging, structuredLoggingFormat);
VMFactory::setKind(jit ? VMKind::JIT : VMKind::Interpreter); VMFactory::setKind(jit ? VMKind::JIT : VMKind::Interpreter);
auto netPrefs = publicIP.empty() ? NetworkPreferences(listenIP ,listenPort, upnp) : NetworkPreferences(publicIP, listenIP ,listenPort, upnp); auto netPrefs = publicIP.empty() ? NetworkPreferences(listenIP ,listenPort, upnp) : NetworkPreferences(publicIP, listenIP ,listenPort, upnp);
@ -469,23 +538,101 @@ int main(int argc, char** argv)
clientImplString, clientImplString,
dbPath, dbPath,
killChain, killChain,
mode == NodeMode::Full ? set<string>{"eth", "shh"} : set<string>(), nodeMode == NodeMode::Full ? set<string>{"eth", "shh"} : set<string>(),
netPrefs, netPrefs,
&nodesState, &nodesState,
miners miners
); );
if (initDAG == LatestBlock || initDAG == PendingBlock) if (mode == OperationMode::DAGInit)
doInitDAG(web3.ethereum()->blockChain().number() + (initDAG == PendingBlock ? 30000 : 0)); doInitDAG(web3.ethereum()->blockChain().number() + (initDAG == PendingBlock ? 30000 : 0));
auto toNumber = [&](string const& s) -> unsigned {
if (s == "latest")
return web3.ethereum()->number();
if (s.size() == 64 || (s.size() == 66 && s.substr(0, 2) == "0x"))
return web3.ethereum()->blockChain().number(h256(s));
try {
return stol(s);
}
catch (...)
{
cerr << "Bad block number/hash option: " << s << endl;
exit(-1);
}
};
if (mode == OperationMode::Export)
{
ofstream fout(filename, std::ofstream::binary);
ostream& out = (filename.empty() || filename == "--") ? cout : fout;
unsigned last = toNumber(exportTo);
for (unsigned i = toNumber(exportFrom); i <= last; ++i)
{
bytes block = web3.ethereum()->blockChain().block(web3.ethereum()->blockChain().numberHash(i));
switch (exportFormat)
{
case Format::Binary: out.write((char const*)block.data(), block.size()); break;
case Format::Hex: out << toHex(block) << endl; break;
case Format::Human: out << RLP(block) << endl; break;
default:;
}
}
return 0;
}
if (mode == OperationMode::Import)
{
ifstream fin(filename, std::ifstream::binary);
istream& in = (filename.empty() || filename == "--") ? cin : fin;
unsigned alreadyHave = 0;
unsigned good = 0;
unsigned futureTime = 0;
unsigned unknownParent = 0;
unsigned bad = 0;
while (in.peek() != -1)
{
bytes block(8);
in.read((char*)block.data(), 8);
block.resize(RLP(block, RLP::LaisezFaire).actualSize());
in.read((char*)block.data() + 8, block.size() - 8);
try
{
web3.ethereum()->injectBlock(block);
good++;
}
catch (AlreadyHaveBlock const&)
{
alreadyHave++;
}
catch (UnknownParent const&)
{
unknownParent++;
}
catch (FutureTime const&)
{
futureTime++;
}
catch (...)
{
bad++;
}
}
cout << (good + bad + futureTime + unknownParent + alreadyHave) << " total: " << good << " ok, " << alreadyHave << " got, " << futureTime << " future, " << unknownParent << " unknown parent, " << bad << " malformed." << endl;
return 0;
}
cout << credits();
web3.setIdealPeerCount(peers); web3.setIdealPeerCount(peers);
std::shared_ptr<eth::BasicGasPricer> gasPricer = make_shared<eth::BasicGasPricer>(u256(double(ether / 1000) / etherPrice), u256(blockFees * 1000)); std::shared_ptr<eth::BasicGasPricer> gasPricer = make_shared<eth::BasicGasPricer>(u256(double(ether / 1000) / etherPrice), u256(blockFees * 1000));
eth::Client* c = mode == NodeMode::Full ? web3.ethereum() : nullptr; eth::Client* c = nodeMode == NodeMode::Full ? web3.ethereum() : nullptr;
StructuredLogger::starting(clientImplString, dev::Version); StructuredLogger::starting(clientImplString, dev::Version);
if (c) if (c)
{ {
c->setGasPricer(gasPricer); c->setGasPricer(gasPricer);
c->setForceMining(forceMining); c->setForceMining(forceMining);
c->setTurboMining(turboMining);
c->setAddress(coinbase); c->setAddress(coinbase);
} }
@ -553,10 +700,9 @@ int main(int argc, char** argv)
} }
else if (cmd == "connect") else if (cmd == "connect")
{ {
string addr; string addrPort;
unsigned port; iss >> addrPort;
iss >> addr >> port; web3.addNode(p2p::NodeId(), addrPort);
web3.addNode(p2p::NodeId(), addr + ":" + toString(port ? port : p2p::c_defaultIPPort));
} }
else if (cmd == "netstop") else if (cmd == "netstop")
{ {

2
libdevcore/Log.cpp

@ -43,7 +43,7 @@ void dev::simpleDebugOut(std::string const& _s, char const*)
static Mutex s_lock; static Mutex s_lock;
Guard l(s_lock); Guard l(s_lock);
cout << _s << endl << flush; cerr << _s << endl << flush;
// helpful to use OutputDebugString on windows // helpful to use OutputDebugString on windows
#ifdef _WIN32 #ifdef _WIN32

2
libdevcore/RLP.cpp

@ -107,7 +107,7 @@ unsigned RLP::actualSize() const
if (isSingleByte()) if (isSingleByte())
return 1; return 1;
if (isData() || isList()) if (isData() || isList())
return payload().data() - m_data.data() + length(); return payloadOffset() + length();
return 0; return 0;
} }

5
libdevcore/RLP.h

@ -290,7 +290,7 @@ public:
RLPs toList() const; RLPs toList() const;
/// @returns the data payload. Valid for all types. /// @returns the data payload. Valid for all types.
bytesConstRef payload() const { return isSingleByte() ? m_data.cropped(0, 1) : m_data.cropped(1 + lengthSize()); } bytesConstRef payload() const { return m_data.cropped(payloadOffset()); }
/// @returns the theoretical size of this item. /// @returns the theoretical size of this item.
/// @note Under normal circumstances, is equivalent to m_data.size() - use that unless you know it won't work. /// @note Under normal circumstances, is equivalent to m_data.size() - use that unless you know it won't work.
@ -309,6 +309,9 @@ private:
/// @returns the size in bytes of the payload, as given by the RLP as opposed to as inferred from m_data. /// @returns the size in bytes of the payload, as given by the RLP as opposed to as inferred from m_data.
unsigned length() const; unsigned length() const;
/// @returns the number of bytes into the data that the payload starts.
unsigned payloadOffset() const { return isSingleByte() ? 0 : (1 + lengthSize()); }
/// @returns the number of data items. /// @returns the number of data items.
unsigned items() const; unsigned items() const;

12
libdevcore/Worker.cpp

@ -29,11 +29,11 @@ using namespace dev;
void Worker::startWorking() void Worker::startWorking()
{ {
cdebug << "startWorking for thread" << m_name; cnote << "startWorking for thread" << m_name;
Guard l(x_work); Guard l(x_work);
if (m_work) if (m_work)
return; return;
cdebug << "Spawning" << m_name; cnote << "Spawning" << m_name;
m_stop = false; m_stop = false;
m_work.reset(new thread([&]() m_work.reset(new thread([&]()
{ {
@ -45,21 +45,21 @@ void Worker::startWorking()
this_thread::sleep_for(chrono::milliseconds(m_idleWaitMs)); this_thread::sleep_for(chrono::milliseconds(m_idleWaitMs));
doWork(); doWork();
} }
cdebug << "Finishing up worker thread"; cnote << "Finishing up worker thread";
doneWorking(); doneWorking();
})); }));
} }
void Worker::stopWorking() void Worker::stopWorking()
{ {
cdebug << "stopWorking for thread" << m_name; cnote << "stopWorking for thread" << m_name;
Guard l(x_work); Guard l(x_work);
if (!m_work) if (!m_work)
return; return;
cdebug << "Stopping" << m_name; cnote << "Stopping" << m_name;
m_stop = true; m_stop = true;
m_work->join(); m_work->join();
m_work.reset(); m_work.reset();
cdebug << "Stopped" << m_name; cnote << "Stopped" << m_name;
} }

6
libdevcrypto/Common.cpp

@ -37,9 +37,9 @@ static Secp256k1 s_secp256k1;
bool dev::SignatureStruct::isValid() const bool dev::SignatureStruct::isValid() const
{ {
if (this->v > 1 || if (v > 1 ||
this->r >= h256("0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141") || r >= h256("0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141") ||
this->s >= h256("0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f")) s >= h256("0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f"))
return false; return false;
return true; return true;
} }

8
libethereum/BlockChain.cpp

@ -240,7 +240,7 @@ void BlockChain::rebuild(std::string const& _path, std::function<void(unsigned,
return; return;
} }
lastHash = bi.hash(); lastHash = bi.hash();
import(b, s.db(), true); import(b, s.db(), Aversion::ImportOldBlocks);
} }
catch (...) catch (...)
{ {
@ -334,7 +334,7 @@ tuple<h256s, h256s, bool> BlockChain::sync(BlockQueue& _bq, OverlayDB const& _st
return make_tuple(fresh, dead, _bq.doneDrain(badBlocks)); return make_tuple(fresh, dead, _bq.doneDrain(badBlocks));
} }
pair<h256s, h256> BlockChain::attemptImport(bytes const& _block, OverlayDB const& _stateDB, bool _force) noexcept pair<h256s, h256> BlockChain::attemptImport(bytes const& _block, OverlayDB const& _stateDB, Aversion _force) noexcept
{ {
try try
{ {
@ -347,7 +347,7 @@ pair<h256s, h256> BlockChain::attemptImport(bytes const& _block, OverlayDB const
} }
} }
pair<h256s, h256> BlockChain::import(bytes const& _block, OverlayDB const& _db, bool _force) pair<h256s, h256> BlockChain::import(bytes const& _block, OverlayDB const& _db, Aversion _force)
{ {
//@tidy This is a behemoth of a method - could do to be split into a few smaller ones. //@tidy This is a behemoth of a method - could do to be split into a few smaller ones.
@ -386,7 +386,7 @@ pair<h256s, h256> BlockChain::import(bytes const& _block, OverlayDB const& _db,
#endif #endif
// Check block doesn't already exist first! // Check block doesn't already exist first!
if (isKnown(bi.hash()) && !_force) if (isKnown(bi.hash()) && _force == Aversion::AvoidOldBlocks)
{ {
clog(BlockChainNote) << bi.hash() << ": Not new."; clog(BlockChainNote) << bi.hash() << ": Not new.";
BOOST_THROW_EXCEPTION(AlreadyHaveBlock()); BOOST_THROW_EXCEPTION(AlreadyHaveBlock());

10
libethereum/BlockChain.h

@ -80,6 +80,12 @@ enum {
using ProgressCallback = std::function<void(unsigned, unsigned)>; using ProgressCallback = std::function<void(unsigned, unsigned)>;
enum class Aversion
{
AvoidOldBlocks,
ImportOldBlocks
};
/** /**
* @brief Implements the blockchain database. All data this gives is disk-backed. * @brief Implements the blockchain database. All data this gives is disk-backed.
* @threadsafe * @threadsafe
@ -102,11 +108,11 @@ public:
/// Attempt to import the given block directly into the CanonBlockChain and sync with the state DB. /// Attempt to import the given block directly into the CanonBlockChain and sync with the state DB.
/// @returns the block hashes of any blocks that came into/went out of the canonical block chain. /// @returns the block hashes of any blocks that came into/went out of the canonical block chain.
std::pair<h256s, h256> attemptImport(bytes const& _block, OverlayDB const& _stateDB, bool _force = false) noexcept; std::pair<h256s, h256> attemptImport(bytes const& _block, OverlayDB const& _stateDB, Aversion _force = Aversion::AvoidOldBlocks) noexcept;
/// Import block into disk-backed DB /// Import block into disk-backed DB
/// @returns the block hashes of any blocks that came into/went out of the canonical block chain. /// @returns the block hashes of any blocks that came into/went out of the canonical block chain.
std::pair<h256s, h256> import(bytes const& _block, OverlayDB const& _stateDB, bool _force = false); std::pair<h256s, h256> import(bytes const& _block, OverlayDB const& _stateDB, Aversion _force = Aversion::AvoidOldBlocks);
/// Returns true if the given block is known (though not necessarily a part of the canon chain). /// Returns true if the given block is known (though not necessarily a part of the canon chain).
bool isKnown(h256 const& _hash) const; bool isKnown(h256 const& _hash) const;

6
libethereum/Client.cpp

@ -397,7 +397,7 @@ void Client::setupState(State& _s)
_s.commitToMine(m_bc); _s.commitToMine(m_bc);
} }
ExecutionResult Client::call(Address _dest, bytes const& _data, u256 _gas, u256 _value, u256 _gasPrice) ExecutionResult Client::call(Address _dest, bytes const& _data, u256 _gas, u256 _value, u256 _gasPrice, Address const& _from)
{ {
ExecutionResult ret; ExecutionResult ret;
try try
@ -407,10 +407,10 @@ ExecutionResult Client::call(Address _dest, bytes const& _data, u256 _gas, u256
{ {
ReadGuard l(x_stateDB); ReadGuard l(x_stateDB);
temp = m_postMine; temp = m_postMine;
temp.addBalance(Address(), _value + _gasPrice * _gas); temp.addBalance(_from, _value + _gasPrice * _gas);
} }
Executive e(temp, LastHashes(), 0); Executive e(temp, LastHashes(), 0);
if (!e.call(_dest, _dest, Address(), _value, _gasPrice, &_data, _gas, Address())) if (!e.call(_dest, _dest, _from, _value, _gasPrice, &_data, _gas, _from))
e.go(); e.go();
ret = e.executionResult(); ret = e.executionResult();
} }

5
libethereum/Client.h

@ -159,7 +159,7 @@ public:
using Interface::call; // to remove warning about hiding virtual function using Interface::call; // to remove warning about hiding virtual function
/// Makes the given call. Nothing is recorded into the state. This cheats by creating a null address and endowing it with a lot of ETH. /// Makes the given call. Nothing is recorded into the state. This cheats by creating a null address and endowing it with a lot of ETH.
ExecutionResult call(Address _dest, bytes const& _data = bytes(), u256 _gas = 125000, u256 _value = 0, u256 _gasPrice = 1 * ether); ExecutionResult call(Address _dest, bytes const& _data = bytes(), u256 _gas = 125000, u256 _value = 0, u256 _gasPrice = 1 * ether, Address const& _from = Address());
/// Get the remaining gas limit in this block. /// Get the remaining gas limit in this block.
virtual u256 gasLimitRemaining() const { return m_postMine.gasLimitRemaining(); } virtual u256 gasLimitRemaining() const { return m_postMine.gasLimitRemaining(); }
@ -229,8 +229,9 @@ public:
protected: protected:
/// InterfaceStub methods /// InterfaceStub methods
virtual BlockChain& bc() override { return m_bc; }
virtual BlockChain const& bc() const override { return m_bc; } virtual BlockChain const& bc() const override { return m_bc; }
/// Returns the state object for the full block (i.e. the terminal state) for index _h. /// Returns the state object for the full block (i.e. the terminal state) for index _h.
/// Works properly with LatestBlock and PendingBlock. /// Works properly with LatestBlock and PendingBlock.
using ClientBase::asOf; using ClientBase::asOf;

19
libethereum/ClientBase.cpp

@ -65,14 +65,17 @@ Address ClientBase::submitTransaction(Secret _secret, u256 _endowment, bytes con
} }
// TODO: remove try/catch, allow exceptions // TODO: remove try/catch, allow exceptions
ExecutionResult ClientBase::call(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber) ExecutionResult ClientBase::call(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber, FudgeFactor _ff)
{ {
ExecutionResult ret; ExecutionResult ret;
try try
{ {
State temp = asOf(_blockNumber); State temp = asOf(_blockNumber);
u256 n = temp.transactionsFrom(toAddress(_secret)); Address a = toAddress(_secret);
u256 n = temp.transactionsFrom(a);
Transaction t(_value, _gasPrice, _gas, _dest, _data, n, _secret); Transaction t(_value, _gasPrice, _gas, _dest, _data, n, _secret);
if (_ff == FudgeFactor::Lenient)
temp.addBalance(a, (u256)(t.gasRequired() * t.gasPrice() + t.value()));
ret = temp.execute(bc().lastHashes(), t, Permanence::Reverted); ret = temp.execute(bc().lastHashes(), t, Permanence::Reverted);
} }
catch (...) catch (...)
@ -82,16 +85,19 @@ ExecutionResult ClientBase::call(Secret _secret, u256 _value, Address _dest, byt
return ret; return ret;
} }
ExecutionResult ClientBase::create(Secret _secret, u256 _value, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber) ExecutionResult ClientBase::create(Secret _secret, u256 _value, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber, FudgeFactor _ff)
{ {
ExecutionResult ret; ExecutionResult ret;
try try
{ {
State temp = asOf(_blockNumber); State temp = asOf(_blockNumber);
u256 n = temp.transactionsFrom(toAddress(_secret)); Address a = toAddress(_secret);
u256 n = temp.transactionsFrom(a);
// cdebug << "Nonce at " << toAddress(_secret) << " pre:" << m_preMine.transactionsFrom(toAddress(_secret)) << " post:" << m_postMine.transactionsFrom(toAddress(_secret)); // cdebug << "Nonce at " << toAddress(_secret) << " pre:" << m_preMine.transactionsFrom(toAddress(_secret)) << " post:" << m_postMine.transactionsFrom(toAddress(_secret));
Transaction t(_value, _gasPrice, _gas, _data, n, _secret); Transaction t(_value, _gasPrice, _gas, _data, n, _secret);
if (_ff == FudgeFactor::Lenient)
temp.addBalance(a, (u256)(t.gasRequired() * t.gasPrice() + t.value()));
ret = temp.execute(bc().lastHashes(), t, Permanence::Reverted); ret = temp.execute(bc().lastHashes(), t, Permanence::Reverted);
} }
catch (...) catch (...)
@ -101,6 +107,11 @@ ExecutionResult ClientBase::create(Secret _secret, u256 _value, bytes const& _da
return ret; return ret;
} }
void ClientBase::injectBlock(bytes const& _block)
{
bc().import(_block, preMine().db());
}
u256 ClientBase::balanceAt(Address _a, BlockNumber _block) const u256 ClientBase::balanceAt(Address _a, BlockNumber _block) const
{ {
return asOf(_block).balance(_a); return asOf(_block).balance(_a);

9
libethereum/ClientBase.h

@ -82,9 +82,10 @@ public:
virtual Address submitTransaction(Secret _secret, u256 _endowment, bytes const& _init, u256 _gas = 10000, u256 _gasPrice = 10 * szabo) override; virtual Address submitTransaction(Secret _secret, u256 _endowment, bytes const& _init, u256 _gas = 10000, u256 _gasPrice = 10 * szabo) override;
/// Makes the given call. Nothing is recorded into the state. /// Makes the given call. Nothing is recorded into the state.
virtual ExecutionResult call(Secret _secret, u256 _value, Address _dest, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = 10 * szabo, BlockNumber _blockNumber = PendingBlock) override; virtual ExecutionResult call(Secret _secret, u256 _value, Address _dest, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = 10 * szabo, BlockNumber _blockNumber = PendingBlock, FudgeFactor _ff = FudgeFactor::Strict) override;
virtual ExecutionResult create(Secret _secret, u256 _value, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = 10 * szabo, BlockNumber _blockNumber = PendingBlock) override; /// Makes the given create. Nothing is recorded into the state.
virtual ExecutionResult create(Secret _secret, u256 _value, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = 10 * szabo, BlockNumber _blockNumber = PendingBlock, FudgeFactor _ff = FudgeFactor::Strict) override;
using Interface::balanceAt; using Interface::balanceAt;
using Interface::countAt; using Interface::countAt;
@ -108,7 +109,6 @@ public:
virtual LocalisedLogEntries peekWatch(unsigned _watchId) const override; virtual LocalisedLogEntries peekWatch(unsigned _watchId) const override;
virtual LocalisedLogEntries checkWatch(unsigned _watchId) override; virtual LocalisedLogEntries checkWatch(unsigned _watchId) override;
// TODO: switch all the _blockHash arguments to also accept _blockNumber
virtual h256 hashFromNumber(BlockNumber _number) const override; virtual h256 hashFromNumber(BlockNumber _number) const override;
virtual eth::BlockInfo blockInfo(h256 _hash) const override; virtual eth::BlockInfo blockInfo(h256 _hash) const override;
virtual eth::BlockDetails blockDetails(h256 _hash) const override; virtual eth::BlockDetails blockDetails(h256 _hash) const override;
@ -124,6 +124,8 @@ public:
virtual eth::Transactions pending() const override; virtual eth::Transactions pending() const override;
virtual h256s pendingHashes() const override; virtual h256s pendingHashes() const override;
void injectBlock(bytes const& _block);
using Interface::diff; using Interface::diff;
virtual StateDiff diff(unsigned _txi, h256 _block) const override; virtual StateDiff diff(unsigned _txi, h256 _block) const override;
virtual StateDiff diff(unsigned _txi, BlockNumber _block) const override; virtual StateDiff diff(unsigned _txi, BlockNumber _block) const override;
@ -154,6 +156,7 @@ public:
protected: protected:
/// The interface that must be implemented in any class deriving this. /// The interface that must be implemented in any class deriving this.
/// { /// {
virtual BlockChain& bc() = 0;
virtual BlockChain const& bc() const = 0; virtual BlockChain const& bc() const = 0;
virtual State asOf(h256 const& _h) const = 0; virtual State asOf(h256 const& _h) const = 0;
virtual State preMine() const = 0; virtual State preMine() const = 0;

14
libethereum/Interface.h

@ -46,6 +46,12 @@ enum class Reaping
Manual Manual
}; };
enum class FudgeFactor
{
Strict,
Lenient
};
/** /**
* @brief Main API hub for interfacing with Ethereum. * @brief Main API hub for interfacing with Ethereum.
*/ */
@ -71,13 +77,13 @@ public:
virtual void flushTransactions() = 0; virtual void flushTransactions() = 0;
/// Makes the given call. Nothing is recorded into the state. /// Makes the given call. Nothing is recorded into the state.
virtual ExecutionResult call(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber) = 0; virtual ExecutionResult call(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber, FudgeFactor _ff = FudgeFactor::Strict) = 0;
ExecutionResult call(Secret _secret, u256 _value, Address _dest, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = 10 * szabo) { return call(_secret, _value, _dest, _data, _gas, _gasPrice, m_default); } ExecutionResult call(Secret _secret, u256 _value, Address _dest, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = 10 * szabo, FudgeFactor _ff = FudgeFactor::Strict) { return call(_secret, _value, _dest, _data, _gas, _gasPrice, m_default, _ff); }
/// Does the given creation. Nothing is recorded into the state. /// Does the given creation. Nothing is recorded into the state.
/// @returns the pair of the Address of the created contract together with its code. /// @returns the pair of the Address of the created contract together with its code.
virtual ExecutionResult create(Secret _secret, u256 _value, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber) = 0; virtual ExecutionResult create(Secret _secret, u256 _value, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber, FudgeFactor _ff = FudgeFactor::Strict) = 0;
ExecutionResult create(Secret _secret, u256 _value, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = 10 * szabo) { return create(_secret, _value, _data, _gas, _gasPrice, m_default); } ExecutionResult create(Secret _secret, u256 _value, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = 10 * szabo, FudgeFactor _ff = FudgeFactor::Strict) { return create(_secret, _value, _data, _gas, _gasPrice, m_default, _ff); }
// [STATE-QUERY API] // [STATE-QUERY API]

11
libethereum/State.cpp

@ -543,8 +543,6 @@ u256 State::enact(bytesConstRef _block, BlockChain const& _bc, bool _checkNonce)
// m_currentBlock is assumed to be prepopulated and reset. // m_currentBlock is assumed to be prepopulated and reset.
BlockInfo bi(_block, _checkNonce ? CheckEverything : IgnoreNonce); BlockInfo bi(_block, _checkNonce ? CheckEverything : IgnoreNonce);
cdebug << "enacting" << BlockInfo::headerHash(_block).abridged() << "==" << bi.hash().abridged() << "on" << m_previousBlock.hash().abridged();
cdebug << m_currentBlock;
#if !ETH_RELEASE #if !ETH_RELEASE
assert(m_previousBlock.hash() == bi.parentHash); assert(m_previousBlock.hash() == bi.parentHash);
@ -560,9 +558,6 @@ u256 State::enact(bytesConstRef _block, BlockChain const& _bc, bool _checkNonce)
m_currentBlock.verifyInternals(_block); m_currentBlock.verifyInternals(_block);
m_currentBlock.noteDirty(); m_currentBlock.noteDirty();
cdebug << "populated and verified. incoming block hash is" << m_currentBlock.hash().abridged();
cdebug << m_currentBlock;
// cnote << "playback begins:" << m_state.root(); // cnote << "playback begins:" << m_state.root();
// cnote << m_state; // cnote << m_state;
@ -631,7 +626,6 @@ u256 State::enact(bytesConstRef _block, BlockChain const& _bc, bool _checkNonce)
// Initialise total difficulty calculation. // Initialise total difficulty calculation.
u256 tdIncrease = m_currentBlock.difficulty; u256 tdIncrease = m_currentBlock.difficulty;
// Check uncles & apply their rewards to state. // Check uncles & apply their rewards to state.
if (rlp[2].itemCount() > 2) if (rlp[2].itemCount() > 2)
BOOST_THROW_EXCEPTION(TooManyUncles()); BOOST_THROW_EXCEPTION(TooManyUncles());
@ -686,11 +680,6 @@ u256 State::enact(bytesConstRef _block, BlockChain const& _bc, bool _checkNonce)
BOOST_THROW_EXCEPTION(InvalidGasUsed() << RequirementError(bigint(gasUsed()), bigint(m_currentBlock.gasUsed))); BOOST_THROW_EXCEPTION(InvalidGasUsed() << RequirementError(bigint(gasUsed()), bigint(m_currentBlock.gasUsed)));
} }
cdebug << m_currentBlock;
auto hh = m_currentBlock.hash();
m_currentBlock.noteDirty();
cdebug << "done enacting. new stateroot is" << m_currentBlock.stateRoot.abridged() << ", hash is" << m_currentBlock.hash().abridged() << " = " << hh;
return tdIncrease; return tdIncrease;
} }

1
libtestutils/FixedClient.h

@ -42,6 +42,7 @@ public:
// stub // stub
virtual void flushTransactions() override {} virtual void flushTransactions() override {}
virtual eth::BlockChain& bc() override { BOOST_THROW_EXCEPTION(InterfaceNotSupported("FixedClient::bc()")); }
virtual eth::BlockChain const& bc() const override { return m_bc; } virtual eth::BlockChain const& bc() const override { return m_bc; }
using ClientBase::asOf; using ClientBase::asOf;
virtual eth::State asOf(h256 const& _h) const override; virtual eth::State asOf(h256 const& _h) const override;

7
libweb3jsonrpc/WebThreeStubServerBase.cpp

@ -497,12 +497,13 @@ string WebThreeStubServerBase::eth_call(Json::Value const& _json, string const&
string ret; string ret;
if (!t.from) if (!t.from)
t.from = m_accounts->getDefaultTransactAccount(); t.from = m_accounts->getDefaultTransactAccount();
if (!m_accounts->isRealAccount(t.from)) // if (!m_accounts->isRealAccount(t.from))
return ret; // return ret;
if (!t.gasPrice) if (!t.gasPrice)
t.gasPrice = 10 * dev::eth::szabo; t.gasPrice = 10 * dev::eth::szabo;
if (!t.gas) if (!t.gas)
t.gas = min<u256>(client()->gasLimitRemaining(), client()->balanceAt(t.from) / t.gasPrice); t.gas = client()->gasLimitRemaining();
ret = toJS(client()->call(m_accounts->secretKey(t.from), t.value, t.to, t.data, t.gas, t.gasPrice, number).output); ret = toJS(client()->call(m_accounts->secretKey(t.from), t.value, t.to, t.data, t.gas, t.gasPrice, number).output);
return ret; return ret;

18
mix/MixClient.cpp

@ -295,12 +295,15 @@ Address MixClient::submitTransaction(Secret _secret, u256 _endowment, bytes cons
return address; return address;
} }
dev::eth::ExecutionResult MixClient::call(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber, bool _gasAuto) dev::eth::ExecutionResult MixClient::call(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber, bool _gasAuto, FudgeFactor _ff)
{ {
(void)_blockNumber; (void)_blockNumber;
Address a = toAddress(_secret);
State temp = asOf(eth::PendingBlock); State temp = asOf(eth::PendingBlock);
u256 n = temp.transactionsFrom(toAddress(_secret)); u256 n = temp.transactionsFrom(a);
Transaction t(_value, _gasPrice, _gas, _dest, _data, n, _secret); Transaction t(_value, _gasPrice, _gas, _dest, _data, n, _secret);
if (_ff == FudgeFactor::Lenient)
temp.addBalance(a, (u256)(t.gasRequired() * t.gasPrice() + t.value()));
bytes rlp = t.rlp(); bytes rlp = t.rlp();
WriteGuard lw(x_state); //TODO: lock is required only for last execution state WriteGuard lw(x_state); //TODO: lock is required only for last execution state
executeTransaction(t, temp, true, _gasAuto, _secret); executeTransaction(t, temp, true, _gasAuto, _secret);
@ -317,22 +320,25 @@ Address MixClient::submitTransaction(Secret _secret, u256 _endowment, bytes cons
return submitTransaction(_secret, _endowment, _init, _gas, _gasPrice, false); return submitTransaction(_secret, _endowment, _init, _gas, _gasPrice, false);
} }
dev::eth::ExecutionResult MixClient::call(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber) dev::eth::ExecutionResult MixClient::call(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber, eth::FudgeFactor _ff)
{ {
return call(_secret, _value, _dest, _data, _gas, _gasPrice, _blockNumber,false); return call(_secret, _value, _dest, _data, _gas, _gasPrice, _blockNumber, false, _ff);
} }
dev::eth::ExecutionResult MixClient::create(Secret _secret, u256 _value, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber) dev::eth::ExecutionResult MixClient::create(Secret _secret, u256 _value, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber, eth::FudgeFactor _ff)
{ {
(void)_blockNumber; (void)_blockNumber;
u256 n; u256 n;
Address a = toAddress(_secret);
State temp; State temp;
{ {
ReadGuard lr(x_state); ReadGuard lr(x_state);
temp = asOf(eth::PendingBlock); temp = asOf(eth::PendingBlock);
n = temp.transactionsFrom(toAddress(_secret)); n = temp.transactionsFrom(a);
} }
Transaction t(_value, _gasPrice, _gas, _data, n, _secret); Transaction t(_value, _gasPrice, _gas, _data, n, _secret);
if (_ff == FudgeFactor::Lenient)
temp.addBalance(a, (u256)(t.gasRequired() * t.gasPrice() + t.value()));
bytes rlp = t.rlp(); bytes rlp = t.rlp();
WriteGuard lw(x_state); //TODO: lock is required only for last execution state WriteGuard lw(x_state); //TODO: lock is required only for last execution state
executeTransaction(t, temp, true, false, _secret); executeTransaction(t, temp, true, false, _secret);

13
mix/MixClient.h

@ -55,12 +55,12 @@ public:
void submitTransaction(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice) override; void submitTransaction(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice) override;
Address submitTransaction(Secret _secret, u256 _endowment, bytes const& _init, u256 _gas, u256 _gasPrice) override; Address submitTransaction(Secret _secret, u256 _endowment, bytes const& _init, u256 _gas, u256 _gasPrice) override;
dev::eth::ExecutionResult call(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, eth::BlockNumber _blockNumber = eth::PendingBlock) override; dev::eth::ExecutionResult call(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, eth::BlockNumber _blockNumber = eth::PendingBlock, eth::FudgeFactor _ff = eth::FudgeFactor::Strict) override;
dev::eth::ExecutionResult create(Secret _secret, u256 _value, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = 10 * eth::szabo, eth::BlockNumber _blockNumber = eth::PendingBlock) override; dev::eth::ExecutionResult create(Secret _secret, u256 _value, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = 10 * eth::szabo, eth::BlockNumber _blockNumber = eth::PendingBlock, eth::FudgeFactor _ff = eth::FudgeFactor::Strict) override;
void submitTransaction(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, bool _gasAuto); void submitTransaction(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, bool _gasAuto);
Address submitTransaction(Secret _secret, u256 _endowment, bytes const& _init, u256 _gas, u256 _gasPrice, bool _gasAuto); Address submitTransaction(Secret _secret, u256 _endowment, bytes const& _init, u256 _gas, u256 _gasPrice, bool _gasAuto);
dev::eth::ExecutionResult call(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, eth::BlockNumber _blockNumber, bool _gasAuto); dev::eth::ExecutionResult call(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, eth::BlockNumber _blockNumber, bool _gasAuto, eth::FudgeFactor _ff = eth::FudgeFactor::Strict);
void setAddress(Address _us) override; void setAddress(Address _us) override;
void setMiningThreads(unsigned _threads) override; void setMiningThreads(unsigned _threads) override;
@ -79,11 +79,10 @@ public:
std::vector<KeyPair> userAccounts() { return m_userAccounts; } std::vector<KeyPair> userAccounts() { return m_userAccounts; }
protected: protected:
virtual dev::eth::BlockChain& bc() { return *m_bc; } /// ClientBase methods
/// InterfaceStub methods
virtual dev::eth::State asOf(h256 const& _block) const override;
using ClientBase::asOf; using ClientBase::asOf;
virtual dev::eth::State asOf(h256 const& _block) const override;
virtual dev::eth::BlockChain& bc() { return *m_bc; }
virtual dev::eth::BlockChain const& bc() const override { return *m_bc; } virtual dev::eth::BlockChain const& bc() const override { return *m_bc; }
virtual dev::eth::State preMine() const override { ReadGuard l(x_state); return m_startState; } virtual dev::eth::State preMine() const override { ReadGuard l(x_state); return m_startState; }
virtual dev::eth::State postMine() const override { ReadGuard l(x_state); return m_state; } virtual dev::eth::State postMine() const override { ReadGuard l(x_state); return m_state; }

169
mix/qml/StateDialog.qml

@ -13,7 +13,7 @@ Dialog {
id: modalStateDialog id: modalStateDialog
modality: Qt.ApplicationModal modality: Qt.ApplicationModal
width: 590 width: 630
height: 480 height: 480
title: qsTr("Edit State") title: qsTr("Edit State")
visible: false visible: false
@ -79,7 +79,10 @@ Dialog {
} }
contentItem: Rectangle { contentItem: Rectangle {
color: stateDialogStyle.generic.backgroundColor color: stateDialogStyle.generic.backgroundColor
ColumnLayout { Rectangle {
color: stateDialogStyle.generic.backgroundColor
anchors.top: parent.top
anchors.margins: 10
anchors.fill: parent anchors.fill: parent
ColumnLayout { ColumnLayout {
anchors.fill: parent anchors.fill: parent
@ -91,7 +94,7 @@ Dialog {
{ {
Layout.fillWidth: true Layout.fillWidth: true
DefaultLabel { DefaultLabel {
Layout.preferredWidth: 75 Layout.preferredWidth: 85
text: qsTr("Title") text: qsTr("Title")
} }
DefaultTextField DefaultTextField
@ -112,10 +115,10 @@ Dialog {
Rectangle Rectangle
{ {
Layout.preferredWidth: 75 Layout.preferredWidth: 85
DefaultLabel { DefaultLabel {
id: accountsLabel id: accountsLabel
Layout.preferredWidth: 75 Layout.preferredWidth: 85
text: qsTr("Accounts") text: qsTr("Accounts")
} }
@ -227,7 +230,7 @@ Dialog {
{ {
Layout.fillWidth: true Layout.fillWidth: true
DefaultLabel { DefaultLabel {
Layout.preferredWidth: 75 Layout.preferredWidth: 85
text: qsTr("Default") text: qsTr("Default")
} }
CheckBox { CheckBox {
@ -240,52 +243,91 @@ Dialog {
{ {
Layout.fillWidth: true Layout.fillWidth: true
} }
}
ColumnLayout {
anchors.top: dialogContent.bottom
anchors.topMargin: 5
spacing: 0
RowLayout RowLayout
{ {
Layout.preferredWidth: 150 Layout.fillWidth: true
DefaultLabel {
text: qsTr("Transactions: ")
}
Button Rectangle
{ {
iconSource: "qrc:/qml/img/plus.png" Layout.preferredWidth: 85
action: newTrAction DefaultLabel {
width: 10 id: transactionsLabel
height: 10 Layout.preferredWidth: 85
anchors.right: parent.right text: qsTr("Transactions")
} }
Action { Button
id: newTrAction {
tooltip: qsTr("Create a new transaction") anchors.top: transactionsLabel.bottom
onTriggered: transactionsModel.addTransaction() anchors.topMargin: 10
iconSource: "qrc:/qml/img/plus.png"
action: newTrAction
}
Action {
id: newTrAction
tooltip: qsTr("Create a new transaction")
onTriggered: transactionsModel.addTransaction()
}
} }
}
ScrollView TableView
{
Layout.fillHeight: true
Layout.preferredWidth: 300
Column
{ {
Layout.fillHeight: true id: transactionsView
Repeater Layout.fillWidth: true
{ model: transactionsModel
id: trRepeater headerVisible: false
model: transactionsModel TableViewColumn {
delegate: transactionRenderDelegate role: "name"
visible: transactionsModel.count > 0 title: qsTr("Name")
height: 20 * transactionsModel.count width: 150
delegate: Item {
RowLayout
{
height: 30
width: parent.width
Button
{
iconSource: "qrc:/qml/img/delete_sign.png"
action: deleteTransactionAction
}
Action {
id: deleteTransactionAction
tooltip: qsTr("Delete")
onTriggered: transactionsModel.deleteTransaction(styleData.row)
}
Button
{
iconSource: "qrc:/qml/img/edit.png"
action: editAction
visible: styleData.row >= 0 ? !transactionsModel.get(styleData.row).stdContract : false
width: 10
height: 10
Action {
id: editAction
tooltip: qsTr("Edit")
onTriggered: transactionsModel.editTransaction(styleData.row)
}
}
DefaultLabel {
Layout.preferredWidth: 150
text: styleData.row >= 0 ? transactionsModel.get(styleData.row).functionId : ""
}
}
}
}
rowDelegate:
Rectangle {
color: styleData.alternate ? "transparent" : "#f0f0f0"
height: 30;
} }
} }
} }
} }
RowLayout RowLayout
@ -293,6 +335,14 @@ Dialog {
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
anchors.right: parent.right; anchors.right: parent.right;
Button {
text: qsTr("Delete");
enabled: !modalStateDialog.isDefault
onClicked: {
projectModel.stateListModel.deleteState(stateIndex);
close();
}
}
Button { Button {
text: qsTr("OK"); text: qsTr("OK");
onClicked: { onClicked: {
@ -325,7 +375,6 @@ Dialog {
} }
function addTransaction() { function addTransaction() {
// Set next id here to work around Qt bug // Set next id here to work around Qt bug
// https://bugreports.qt-project.org/browse/QTBUG-41327 // https://bugreports.qt-project.org/browse/QTBUG-41327
// Second call to signal handler would just edit the item that was just created, no harm done // Second call to signal handler would just edit the item that was just created, no harm done
@ -350,44 +399,6 @@ Dialog {
} }
} }
Component {
id: transactionRenderDelegate
RowLayout {
DefaultLabel {
Layout.preferredWidth: 150
text: functionId
}
Button
{
id: deleteBtn
iconSource: "qrc:/qml/img/delete_sign.png"
action: deleteAction
width: 10
height: 10
Action {
id: deleteAction
tooltip: qsTr("Delete")
onTriggered: transactionsModel.deleteTransaction(index)
}
}
Button
{
iconSource: "qrc:/qml/img/edit.png"
action: editAction
visible: stdContract === false
width: 10
height: 10
Action {
id: editAction
tooltip: qsTr("Edit")
onTriggered: transactionsModel.editTransaction(index)
}
}
}
}
TransactionDialog TransactionDialog
{ {
id: transactionDialog id: transactionDialog

4
mix/qml/StateListModel.qml

@ -167,6 +167,7 @@ Item {
signal defaultStateChanged; signal defaultStateChanged;
signal stateListModelReady; signal stateListModelReady;
signal stateRun(int index) signal stateRun(int index)
signal stateDeleted(int index)
function defaultTransactionItem() { function defaultTransactionItem() {
return TransactionHelper.defaultTransaction(); return TransactionHelper.defaultTransaction();
@ -293,9 +294,8 @@ Item {
} }
else if (defaultStateIndex > index) else if (defaultStateIndex > index)
defaultStateIndex--; defaultStateIndex--;
save(); save();
stateDeleted(index);
} }
function save() { function save() {

31
mix/qml/StatusPane.qml

@ -3,6 +3,7 @@ import QtQuick.Controls 1.1
import QtQuick.Layouts 1.1 import QtQuick.Layouts 1.1
import QtQuick.Controls.Styles 1.3 import QtQuick.Controls.Styles 1.3
import org.ethereum.qml.InverseMouseArea 1.0 import org.ethereum.qml.InverseMouseArea 1.0
import QtGraphicalEffects 1.0
import "js/ErrorLocationFormater.js" as ErrorLocationFormater import "js/ErrorLocationFormater.js" as ErrorLocationFormater
import "." import "."
@ -246,6 +247,27 @@ Rectangle {
tooltip: "" tooltip: ""
} }
Rectangle
{
id: logsShadow
width: logsContainer.width + 5
height: 0
opacity: 0.3
clip: true
anchors.top: logsContainer.top
anchors.margins: 4
Rectangle {
color: "gray"
anchors.top: parent.top
radius: 10
id: roundRect
height: 400
width: parent.width
}
}
Rectangle Rectangle
{ {
InverseMouseArea InverseMouseArea
@ -287,9 +309,16 @@ Rectangle {
top = top.parent top = top.parent
var coordinates = logsContainer.mapToItem(top, 0, 0); var coordinates = logsContainer.mapToItem(top, 0, 0);
logsContainer.parent = top; logsContainer.parent = top;
logsShadow.parent = top;
logsContainer.x = status.x + statusContainer.x - logStyle.generic.layout.dateWidth - logStyle.generic.layout.typeWidth + 70 logsContainer.x = status.x + statusContainer.x - logStyle.generic.layout.dateWidth - logStyle.generic.layout.typeWidth + 70
logsShadow.x = status.x + statusContainer.x - logStyle.generic.layout.dateWidth - logStyle.generic.layout.typeWidth + 70;
logsShadow.z = 1
logsContainer.z = 2
if (Qt.platform.os === "osx") if (Qt.platform.os === "osx")
{
logsContainer.y = statusContainer.y; logsContainer.y = statusContainer.y;
logsShadow.y = statusContainer.y;
}
} }
LogsPaneStyle { LogsPaneStyle {
@ -305,6 +334,7 @@ Rectangle {
State { State {
name: "opened"; name: "opened";
PropertyChanges { target: logsContainer; height: 500; visible: true } PropertyChanges { target: logsContainer; height: 500; visible: true }
PropertyChanges { target: logsShadow; height: 500; visible: true }
PropertyChanges { target: outsideClick; active: true } PropertyChanges { target: outsideClick; active: true }
}, },
@ -313,6 +343,7 @@ Rectangle {
PropertyChanges { target: logsContainer; height: 0; visible: false } PropertyChanges { target: logsContainer; height: 0; visible: false }
PropertyChanges { target: statusContainer; width: 600; height: 30 } PropertyChanges { target: statusContainer; width: 600; height: 30 }
PropertyChanges { target: outsideClick; active: false } PropertyChanges { target: outsideClick; active: false }
PropertyChanges { target: logsShadow; height: 0; visible: false }
} }
] ]
transitions: Transition { transitions: Transition {

1
mix/qml/TransactionDialog.qml

@ -400,7 +400,6 @@ Dialog {
Button { Button {
text: qsTr("Cancel"); text: qsTr("Cancel");
onClicked: close(); onClicked: close();
Layout.fillWidth: true
} }
} }
} }

10
mix/qml/TransactionLog.qml

@ -52,7 +52,7 @@ Item {
{ {
id: statesCombo id: statesCombo
items: projectModel.stateListModel items: projectModel.stateListModel
onSelectCreate: projectModel.stateListModel.addState(); onSelectCreate: projectModel.stateListModel.addState()
onEditItem: projectModel.stateListModel.editState(item) onEditItem: projectModel.stateListModel.editState(item)
colorItem: "#808080" colorItem: "#808080"
colorSelect: "#4a90e2" colorSelect: "#4a90e2"
@ -63,8 +63,16 @@ Item {
if (statesCombo.selectedIndex !== index) if (statesCombo.selectedIndex !== index)
statesCombo.setSelectedIndex(index) statesCombo.setSelectedIndex(index)
} }
onStateListModelReady: {
statesCombo.setSelectedIndex(projectModel.stateListModel.defaultStateIndex)
}
onStateDeleted: {
if (index === statesCombo.selectedIndex)
statesCombo.setSelectedIndex(0);
}
} }
} }
Button Button
{ {
anchors.rightMargin: 9 anchors.rightMargin: 9

Loading…
Cancel
Save