From d3d4d0a2f881d96c291d00aaeb305bf53715ab09 Mon Sep 17 00:00:00 2001 From: Vincent Gariepy Date: Mon, 7 Apr 2014 03:47:39 -0400 Subject: [PATCH 1/5] ncurses forms, Addresses window with NameReg, fix contracts showing twice, mining indicator and other small fixes --- eth/CMakeLists.txt | 3 + eth/main.cpp | 493 ++++++++++++++++++++++++++++++++++++++------- 2 files changed, 428 insertions(+), 68 deletions(-) diff --git a/eth/CMakeLists.txt b/eth/CMakeLists.txt index 704568b32..54f26ccee 100644 --- a/eth/CMakeLists.txt +++ b/eth/CMakeLists.txt @@ -17,17 +17,20 @@ if (${TARGET_PLATFORM} STREQUAL "w64") target_link_libraries(eth iphlpapi) target_link_libraries(eth cryptopp) target_link_libraries(eth ncurses) + target_link_libraries(eth form) target_link_libraries(eth boost_system-mt-s) target_link_libraries(eth boost_filesystem-mt-s) target_link_libraries(eth boost_thread_win32-mt-s) set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS) elseif (UNIX) target_link_libraries(eth ncurses) + target_link_libraries(eth form) else () target_link_libraries(eth ${CRYPTOPP_LIBRARIES}) target_link_libraries(eth boost_system) target_link_libraries(eth boost_filesystem) target_link_libraries(eth ncurses) + target_link_libraries(eth form) find_package(Threads REQUIRED) target_link_libraries(eth ${CMAKE_THREAD_LIBS_INIT}) endif () diff --git a/eth/main.cpp b/eth/main.cpp index 71217bb69..afe59fff2 100644 --- a/eth/main.cpp +++ b/eth/main.cpp @@ -22,6 +22,8 @@ #include #undef OK +#include +#undef OK #include #include #include @@ -88,8 +90,9 @@ void interactiveHelp() << " block Gives the current block height." << endl << " balance Gives the current balance." << endl << " peers List the peers that are connected" << endl - << " transact Executes a given transaction." << endl - << " send Executes a given transaction with current secret." << endl + << " transact Execute a given transaction." << endl + << " send Execute a given transaction with current secret." << endl + << " contract Create a new contract with current secret." << endl << " inspect Dumps a contract to /.evm." << endl << " exit Exits the application." << endl; } @@ -127,6 +130,25 @@ void version() exit(0); } +u256 c_minGasPrice = 10000000000000; +u256 c_minGas = 100; +Address c_config = Address("ccdeac59d35627b7de09332e819d5159e7bb7250"); +string pretty(h160 _a, eth::State _st) +{ + string ns; + h256 n; + if (h160 nameReg = (u160)_st.contractStorage(c_config, 0)) + n = _st.contractStorage(nameReg, (u160)(_a)); + if (n) + { + std::string s((char const*)n.data(), 32); + if (s.find_first_of('\0') != string::npos) + s.resize(s.find_first_of('\0')); + ns = " " + s; + } + return ns; +} + namespace nc { @@ -254,6 +276,8 @@ int nc_window_streambuf::sync() } +vector form_dialog(vector _sfields, vector _lfields, vector _bfields, int _cols, int _rows, string _post_form); + int main(int argc, char** argv) { @@ -382,7 +406,7 @@ int main(int argc, char** argv) int y = 0; int x = 2; string cmd; - WINDOW * mainwin, * consolewin, * logwin, * blockswin, * pendingwin, * contractswin, * peerswin; + WINDOW * mainwin, * consolewin, * logwin, * blockswin, * pendingwin, *addswin, * contractswin, * peerswin; if (!(mainwin = initscr())) { @@ -391,34 +415,43 @@ int main(int argc, char** argv) } getmaxyx(mainwin, height, width); + int qheight = height * 3 / 5; int qwidth = width / 4 - 4; nonl(); - nocbreak(); + cbreak(); timeout(30000); echo(); keypad(mainwin, true); - logwin = newwin(height * 2 / 5 - 2, width, height * 3 / 5, 0); + /* Initialize color pairs */ + start_color(); + init_pair(1, COLOR_WHITE, COLOR_BLACK); + init_pair(2, COLOR_RED, COLOR_BLACK); + init_pair(3, 7, COLOR_BLACK); + use_default_colors(); + + logwin = newwin(height * 2 / 5 - 2, width * 2 / 3, qheight, 0); nc::nc_window_streambuf outbuf(logwin, std::cout); - // nc::nc_window_streambuf errbuf( logwin, std::cerr ); g_logVerbosity = 1; // Force verbosity level for now - consolewin = newwin(height * 3 / 5, width / 4, 0, 0); + consolewin = newwin(qheight, width / 4, 0, 0); nc::nc_window_streambuf coutbuf(consolewin, ccout); - blockswin = newwin(height * 3 / 5, width / 4, 0, width / 4); + blockswin = newwin(qheight, width / 4, 0, width / 4); pendingwin = newwin(height * 1 / 5, width / 4, 0, width * 2 / 4); peerswin = newwin(height * 2 / 5, width / 4, height * 1 / 5, width * 2 / 4); - contractswin = newwin(height * 3 / 5, width / 4, 0, width * 3 / 4); + addswin = newwin(height * 2 / 5 - 2, width / 3, qheight, width * 2 / 3); + contractswin = newwin(qheight, width / 4, 0, width * 3 / 4); - int vl = height * 3 / 5 - 4; + int vl = qheight - 4; wsetscrreg(consolewin, 1, vl); wsetscrreg(blockswin, 1, vl); wsetscrreg(pendingwin, 1, vl); wsetscrreg(peerswin, 1, vl); + wsetscrreg(addswin, 1, vl); wsetscrreg(contractswin, 1, vl); - mvwprintw(mainwin, 1, x, "> "); + mvwprintw(mainwin, 1, 1, " > "); wresize(mainwin, 3, width); mvwin(mainwin, height - 3, 0); @@ -432,6 +465,7 @@ int main(int argc, char** argv) wclrtobot(consolewin); wclrtobot(pendingwin); wclrtobot(peerswin); + wclrtobot(addswin); wclrtobot(contractswin); ccout << credits(true); @@ -449,7 +483,7 @@ int main(int argc, char** argv) chr = toHex(us.address().asArray()).c_str(); ccout << chr << endl << endl; - mvwprintw(mainwin, 1, x, "> "); + mvwprintw(mainwin, 1, 1, " > "); clrtoeol(); if (s.length() > 1) @@ -512,28 +546,143 @@ int main(int argc, char** argv) } else if (cmd == "transact") { - string sechex; - string rechex; - u256 amount; - u256 gasPrice; - u256 gas; - iss >> sechex >> rechex >> amount >> gasPrice >> gas; - Secret secret = h256(fromHex(sechex)); - Address dest = h160(fromHex(rechex)); - bytes data; - - c.transact(secret, amount, dest, data, gas, gasPrice); + vector s; + s.push_back("Address"); + vector l; + l.push_back("Amount"); + l.push_back("Gas price"); + l.push_back("Gas"); + vector b; + b.push_back("Secret"); + b.push_back("Data"); + c.lock(); + vector fields = form_dialog(s, l, b, height, width, cmd); + c.unlock(); + int fs = fields.size(); + if (fs < 6) + { + if (fs > 0) + cwarn << "Missing parameter"; + } + else { + fields[0].erase(std::remove(fields[0].begin(), fields[0].end(), ' '), fields[0].end()); + fields[4].erase(std::remove(fields[4].begin(), fields[4].end(), ' '), fields[4].end()); + fields[5].erase(std::find_if(fields[5].rbegin(), fields[5].rend(), std::bind1st(std::not_equal_to(), ' ')).base(), fields[5].end()); + int size = fields[0].length(); + u256 amount = atoll(fields[1].c_str()); + u256 gasPrice = atoll(fields[2].c_str()); + u256 gas = atoll(fields[3].c_str()); + string sechex = fields[4]; + string sdata = fields[5]; + int ssize = fields[4].length(); + if (size < 40) { + if (size > 0) + cwarn << "Invalid address length: " << size; + } + else if (amount < 0) + cwarn << "Invalid amount: " << amount; + else if (gasPrice < c_minGasPrice) + cwarn << "Minimum gas price is " << c_minGasPrice; + else if (gas < c_minGas) + cwarn << "Minimum gas amount is " << c_minGas; + else if (ssize < 40) + { + if (ssize > 0) + cwarn << "Invalid secret length:" << ssize; + } + else { + Secret secret = h256(fromHex(sechex)); + Address dest = h160(fromHex(fields[0])); + bytes data = asBytes(sdata); + c.transact(secret, amount, dest, data, gas, gasPrice); + } + } } else if (cmd == "send") { - string rechex; - u256 amount; - u256 gasPrice; - u256 gas; - iss >> rechex >> amount >> gasPrice >> gas; - Address dest = h160(fromHex(rechex)); - - c.transact(us.secret(), amount, dest, bytes(), gas, gasPrice); + vector s; + s.push_back("Address"); + vector l; + l.push_back("Amount"); + vector b; + c.lock(); + vector fields = form_dialog(s, l, b, height, width, cmd); + c.unlock(); + int fs = fields.size(); + if (fs < 2) + { + if (fs > 0) + cwarn << "Missing parameter"; + } + else { + fields[0].erase(std::remove(fields[0].begin(), fields[0].end(), ' '), fields[0].end()); + int size = fields[0].length(); + u256 amount = atoll(fields[1].c_str()); + if (size < 40) { + if (size > 0) + cwarn << "Invalid address length: " << size; + } + else if (amount <= 0) + cwarn << "Invalid amount: " << amount; + else + { + u256 gasPrice = c_minGasPrice; + u256 gas = c_minGas; + Address dest = h160(fromHex(fields[0])); + c.transact(us.secret(), amount, dest, bytes(), gas, gasPrice); + } + } + } + else if (cmd == "contract") + { + vector s; + vector l; + l.push_back("Endowment"); + l.push_back("Gas price"); + l.push_back("Gas"); + vector b; + b.push_back("Code"); + b.push_back("Init"); + c.lock(); + vector fields = form_dialog(s, l, b, height, width, cmd); + c.unlock(); + int fs = fields.size(); + if (fs < 5) { + if (fs > 0) + cwarn << "Missing parameter"; + } + else { + u256 endowment = atoll(fields[0].c_str()); + u256 gas = atoll(fields[2].c_str()); + u256 gasPrice = atoll(fields[1].c_str()); + if (endowment < 0) + cwarn << "Invalid endowment"; + else if (gasPrice < c_minGasPrice) + cwarn << "Minimum gas price is " << c_minGasPrice; + else if (gas < c_minGas) + cwarn << "Minimum gas amount is " << c_minGas; + else + { + fields[3].erase(std::find_if(fields[3].rbegin(), fields[3].rend(), std::bind1st(std::not_equal_to(), ' ')).base(), fields[3].end()); + fields[4].erase(std::find_if(fields[4].rbegin(), fields[4].rend(), std::bind1st(std::not_equal_to(), ' ')).base(), fields[4].end()); + string scode = fields[3]; + string sinit = fields[4]; + int size = scode.length(); + cout << "Code:" << endl << scode << endl; + cout << "Init:" << endl << sinit << endl; + cout << "Code size: " << size << endl; + if (size < 1) + cwarn << "No code submitted"; + else + { + eth::bytes code = assemble(scode); + cout << "Assembled:" << endl << code << endl; + eth::bytes init = assemble(sinit); + cout << "Init:" << endl << init << endl; + c.transact(us.secret(), endowment, code, init, gas, gasPrice); + } + } + } } else if (cmd == "inspect") { @@ -541,7 +690,7 @@ int main(int argc, char** argv) iss >> rechex; if (rechex.length() != 40) - cout << "Invalid address length" << endl; + cwarn << "Invalid address length"; else { c.lock(); @@ -605,13 +754,12 @@ int main(int argc, char** argv) // Blocks auto const& st = c.state(); auto const& bc = c.blockChain(); - y = 0; + y = 1; for (auto h = bc.currentHash(); h != bc.genesisHash(); h = bc.details(h).parent) { auto d = bc.details(h); string s = "# " + std::to_string(d.number) + ' ' + toString(h); // .abridged(); - y += 1; - mvwaddnstr(blockswin, y, x, s.c_str(), qwidth); + mvwaddnstr(blockswin, y++, x, s.c_str(), qwidth); for (auto const& i: RLP(bc.block(h))[1]) { @@ -620,53 +768,57 @@ int main(int argc, char** argv) ss = t.receiveAddress ? " " + toString(toHex(t.safeSender().asArray())) + " " + (st.isContractAddress(t.receiveAddress) ? '*' : '-') + "> " + toString(t.receiveAddress) + ": " + toString(formatBalance(t.value)) + " [" + toString((unsigned)t.nonce) + "]": " " + toString(toHex(t.safeSender().asArray())) + " +> " + toString(right160(t.sha3())) + ": " + toString(formatBalance(t.value)) + " [" + toString((unsigned)t.nonce) + "]"; - y += 1; - mvwaddnstr(blockswin, y, x, ss.c_str(), qwidth - 2); - if (y > height * 3 / 5 - 2) + mvwaddnstr(blockswin, y++, x, ss.c_str(), qwidth - 2); + if (y > qheight - 2) break; } - if (y > height * 3 / 5 - 2) + if (y > qheight - 2) break; } // Pending - y = 0; - for (Transaction const& t: c.pending()) + y = 1; + auto aps = c.pending(); + for (auto const& t: aps) { string ss; if (t.receiveAddress) ss = toString(toHex(t.safeSender().asArray())) + " " + (st.isContractAddress(t.receiveAddress) ? '*' : '-') + "> " + toString(t.receiveAddress) + ": " + toString(formatBalance(t.value)) + " " + " [" + toString((unsigned)t.nonce) + "]"; else ss = toString(toHex(t.safeSender().asArray())) + " +> " + toString(right160(t.sha3())) + ": " + toString(formatBalance(t.value)) + "[" + toString((unsigned)t.nonce) + "]"; - y += 1; - mvwaddnstr(pendingwin, y, x, ss.c_str(), qwidth); - if (y > height * 3 / 5 - 4) + mvwaddnstr(pendingwin, y++, x, ss.c_str(), qwidth); + if (y > qheight - 4) break; } - // Contracts + // Contracts and addresses + y = 1; + int cc = 1; auto acs = st.addresses(); - y = 0; - for (auto n = 0; n < 2; ++n) - for (auto const& i: acs) - { - auto r = i.first; + for (auto const& i: acs) + { + auto r = i.first; - if (st.isContractAddress(r)) - { - string ss; - ss = toString(r) + " : " + toString(formatBalance(i.second)) + " [" + toString((unsigned)st.transactionsFrom(i.first)) + "]"; - y += 1; - mvwaddnstr(contractswin, y, x, ss.c_str(), qwidth); - if (y > height * 3 / 5 - 2) - break; - } + string ss; + ss = toString(r) + pretty(r, st) + " : " + toString(formatBalance(i.second)) + " [" + toString((unsigned)st.transactionsFrom(i.first)) + "]"; + mvwaddnstr(addswin, y++, x, ss.c_str(), width / 2 - 4); + scrollok(addswin, true); + + if (st.isContractAddress(r)) + { + ss = toString(r) + " : " + toString(formatBalance(i.second)) + " [" + toString((unsigned)st.transactionsFrom(i.first)) + "]"; + mvwaddnstr(contractswin, cc++, x, ss.c_str(), qwidth); + if (cc > qheight - 2) + break; } + if (y > height * 2 / 5 - 2) + break; + } // Peers - y = 0; + y = 1; string psc; string pss; auto cp = c.peers(); @@ -674,8 +826,7 @@ int main(int argc, char** argv) for (PeerInfo const& i: cp) { pss = toString(chrono::duration_cast(i.lastPing).count()) + " ms - " + i.host + ":" + toString(i.port) + " - " + i.clientVersion; - y += 1; - mvwaddnstr(peerswin, y, x, pss.c_str(), qwidth); + mvwaddnstr(peerswin, y++, x, pss.c_str(), qwidth); if (y > height * 2 / 5 - 4) break; } @@ -684,15 +835,18 @@ int main(int argc, char** argv) box(blockswin, 0, 0); box(pendingwin, 0, 0); box(peerswin, 0, 0); + box(addswin, 0, 0); box(contractswin, 0, 0); box(mainwin, 0, 0); // Balance - mvwprintw(consolewin, 0, x, "Balance: "); + stringstream ssb; u256 balance = c.state().balance(us.address()); - chr = toString(balance).c_str(); - mvwprintw(consolewin, 0, 11, chr); - wmove(consolewin, 1, x); + Address gavCoin("91a10664d0cd489085a7a018beb5245d4f2272f1"); + u256 totalGavCoinBalance = st.contractStorage(gavCoin, (u160)us.address()); + ssb << "Balance: " << formatBalance(balance) << " | " << totalGavCoinBalance << " GAV"; + mvwprintw(consolewin, 0, x, ssb.str().c_str()); + mvwprintw(consolewin, 0, x, ssb.str().c_str()); // Block mvwprintw(blockswin, 0, x, "Block # "); @@ -700,22 +854,45 @@ int main(int argc, char** argv) chr = toString(n).c_str(); mvwprintw(blockswin, 0, 10, chr); - mvwprintw(pendingwin, 0, x, "Pending"); - mvwprintw(contractswin, 0, x, "Contracts"); + // Pending + string pc; + pc = "Pending: " + toString(c.pending().size()); + mvwprintw(pendingwin, 0, x, pc.c_str()); + + // Contracts + string sc = "Contracts: "; + sc += toString(cc - 1); + mvwprintw(contractswin, 0, x, sc.c_str()); // Peers mvwprintw(peerswin, 0, x, "Peers: "); chr = toString(c.peers().size()).c_str(); mvwprintw(peerswin, 0, 9, chr); + // Mining flag + if (c.isMining()) + mvwprintw(consolewin, qheight - 1, width / 4 - 11, "Mining ON"); + else + mvwprintw(consolewin, qheight - 1, width / 4 - 12, "Mining OFF"); + + wmove(consolewin, 1, x); + + // Addresses + string ac; + ac = "Addresses: " + toString(acs.size()); + mvwprintw(addswin, 0, x, ac.c_str()); + + wrefresh(consolewin); wrefresh(blockswin); wrefresh(pendingwin); wrefresh(peerswin); + wrefresh(addswin); wrefresh(contractswin); wrefresh(mainwin); } + delwin(addswin); delwin(contractswin); delwin(peerswin); delwin(pendingwin); @@ -744,3 +921,183 @@ int main(int argc, char** argv) return 0; } + +void print_in_middle(WINDOW *win, int starty, int startx, int width, string str, chtype color) +{ + int length; + int x = 0; + int y = 0; + float temp; + + if (startx != 0) + x = startx; + if (starty != 0) + y = starty; + if (width == 0) + width = 80; + + length = str.length(); + temp = (width - length) / 2; + x = startx + (int)temp; + wattron(win, color); + mvwprintw(win, y, x, "%s", str.c_str()); + wattroff(win, color); + refresh(); +} + +vector form_dialog(vector _sv, vector _lv, vector _bv, int _cols, int _rows, string _post_form) +{ + vector vs; + WINDOW *form_win; + int _sfields = _sv.size(); + int _lfields = _lv.size(); + int _bfields = _bv.size(); + int maxfields = _sfields + _lfields + _bfields; + FIELD *field[maxfields]; + int ch; + int starty = 6; + int height = _cols; + int width = _rows; + + /* Initialize the fields */ + int si; + int li; + int bi = 0; + vector labels; + for (si = 0; si < _sfields; ++si) + { + starty++; // Leave room for our labels, no window yet so that or fake fields... + field[si] = new_field(1, 40, starty++, 1, 0, 0); + labels.push_back(starty); + set_field_back(field[si], A_UNDERLINE); + set_field_type(field[si], TYPE_ALNUM, 40); + } + for (li = _sfields; li < _sfields + _lfields; ++li) + { + starty++; + field[li] = new_field(1, 64, starty++, 1, 3, 0); + labels.push_back(starty); + set_field_back(field[li], A_UNDERLINE); + } + for (bi = _sfields + _lfields; bi < maxfields; ++bi) + { + starty++; + field[bi] = new_field(5, 72, starty++, 1, 0, 0); + labels.push_back(starty); + field_opts_off(field[bi], O_STATIC); + set_field_back(field[bi], A_UNDERLINE); + starty += 4; + } + field[maxfields] = NULL; + + /* Create the form and post it */ + FORM *form = new_form(field); + + /* Calculate the area required for the form */ + scale_form(form, &_rows, &_cols); + + /* Create the window to be associated with the form */ + form_win = newwin(_rows + 4, _cols + 8, (height / 2 - _rows / 2 - 2), (width / 2 - _cols / 2 - 2)); + + /* Set main window and sub window */ + set_form_win(form, form_win); + set_form_sub(form, derwin(form_win, _rows, _cols, 2, 2)); + + nodelay(form_win, true); + keypad(form_win, true); + noecho(); + timeout(0); + + box(form_win, 0, 0); + print_in_middle(form_win, 1, 0, _cols, _post_form, COLOR_PAIR(2)); + + post_form(form); + + // Set labels + int ca = 0; + int cf; + for (cf = 0; cf < _sfields; ++cf) + { + wattron(form_win, COLOR_PAIR(3)); + mvwprintw(form_win, labels[ca], 3, _sv[cf].c_str()); + wattroff(form_win, COLOR_PAIR(3)); + ca++; + } + for (cf = 0; cf < _lfields; ++cf) + { + wattron(form_win, COLOR_PAIR(3)); + mvwprintw(form_win, labels[ca], 3, _lv[cf].c_str()); + mvwprintw(form_win, labels[ca] + 1, _cols - 1, "wei"); + wattroff(form_win, COLOR_PAIR(3)); + ca++; + } + for (cf = 0; cf < _bfields; ++cf) + { + wattron(form_win, COLOR_PAIR(3)); + mvwprintw(form_win, labels[ca], 3, _bv[cf].c_str()); + wattroff(form_win, COLOR_PAIR(3)); + ca++; + } + + wrefresh(form_win); + + print_in_middle(form_win, 3, 0, _cols, string("Use the TAB key to switch between fields."), COLOR_PAIR(1)); + print_in_middle(form_win, 4, 0, _cols, string("Use UP, DOWN arrow keys to switch between lines."), COLOR_PAIR(1)); + print_in_middle(form_win, 6, 0, _cols, string("Press ENTER to submit the form and ESC to cancel."), COLOR_PAIR(1)); + refresh(); + + while ((ch = wgetch(form_win)) != 27 and ch != 13) // KEY_F(1)) + { + switch (ch) + { + case 9: // Tab + form_driver(form, REQ_NEXT_FIELD); + form_driver(form, REQ_END_LINE); + break; + case KEY_DOWN: + form_driver(form, REQ_NEXT_LINE); + break; + case KEY_UP: + form_driver(form, REQ_PREV_LINE); + break; + case KEY_LEFT: + form_driver(form, REQ_LEFT_CHAR); + break; + case KEY_RIGHT: + form_driver(form, REQ_RIGHT_CHAR); + break; + case KEY_BACKSPACE: // Backspace + case KEY_DC: + case KEY_DL: + case 127: + form_driver(form, REQ_DEL_PREV); + wrefresh(form_win); + break; + case KEY_ENTER: // Enter + case 13: + case 27: // Esc + break; + default: + form_driver(form, ch); + break; + } + } + + if (form_driver(form, REQ_VALIDATION) != E_OK) + cwarn << "Validation error"; + + int fi; + for (fi = 0; fi < maxfields; ++fi) + free_field(field[fi]); + free_form(form); + unpost_form(form); + echo(); + timeout(30000); + delwin(form_win); + + if (ch == 13) + for (int fi = 0; fi < maxfields; ++fi) + vs.push_back(field_buffer(field[fi], 0)); + + return vs; +} From 4c304d8c8077b12897f82daa19571cdeeac2ca02 Mon Sep 17 00:00:00 2001 From: Vincent Gariepy Date: Mon, 7 Apr 2014 04:27:50 -0400 Subject: [PATCH 2/5] one mvwprintw too many --- eth/main.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/eth/main.cpp b/eth/main.cpp index afe59fff2..20e09b4d8 100644 --- a/eth/main.cpp +++ b/eth/main.cpp @@ -846,7 +846,6 @@ int main(int argc, char** argv) u256 totalGavCoinBalance = st.contractStorage(gavCoin, (u160)us.address()); ssb << "Balance: " << formatBalance(balance) << " | " << totalGavCoinBalance << " GAV"; mvwprintw(consolewin, 0, x, ssb.str().c_str()); - mvwprintw(consolewin, 0, x, ssb.str().c_str()); // Block mvwprintw(blockswin, 0, x, "Block # "); From dfd5d4b16f464a533effa20ac4f2c09c0df28ac0 Mon Sep 17 00:00:00 2001 From: Vincent Gariepy Date: Mon, 7 Apr 2014 17:38:33 -0400 Subject: [PATCH 3/5] coding standards --- eth/main.cpp | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/eth/main.cpp b/eth/main.cpp index 20e09b4d8..7c5f51be4 100644 --- a/eth/main.cpp +++ b/eth/main.cpp @@ -398,7 +398,7 @@ int main(int argc, char** argv) { std::ostringstream ccout; - /* Initialize ncurses */ + // Initialize ncurses const char* chr; char* str = new char[255]; int width; @@ -424,7 +424,7 @@ int main(int argc, char** argv) echo(); keypad(mainwin, true); - /* Initialize color pairs */ + // Initialize color pairs start_color(); init_pair(1, COLOR_WHITE, COLOR_BLACK); init_pair(2, COLOR_RED, COLOR_BLACK); @@ -564,7 +564,8 @@ int main(int argc, char** argv) if (fs > 0) cwarn << "Missing parameter"; } - else { + else + { fields[0].erase(std::remove(fields[0].begin(), fields[0].end(), ' '), fields[0].end()); fields[4].erase(std::remove(fields[4].begin(), fields[4].end(), ' '), fields[4].end()); fields[5].erase(std::find_if(fields[5].rbegin(), fields[5].rend(), std::bind1st(std::not_equal_to(), ' ')).base(), fields[5].end()); @@ -590,7 +591,8 @@ int main(int argc, char** argv) if (ssize > 0) cwarn << "Invalid secret length:" << ssize; } - else { + else + { Secret secret = h256(fromHex(sechex)); Address dest = h160(fromHex(fields[0])); bytes data = asBytes(sdata); @@ -614,7 +616,8 @@ int main(int argc, char** argv) if (fs > 0) cwarn << "Missing parameter"; } - else { + else + { fields[0].erase(std::remove(fields[0].begin(), fields[0].end(), ' '), fields[0].end()); int size = fields[0].length(); u256 amount = atoll(fields[1].c_str()); @@ -647,11 +650,13 @@ int main(int argc, char** argv) vector fields = form_dialog(s, l, b, height, width, cmd); c.unlock(); int fs = fields.size(); - if (fs < 5) { + if (fs < 5) + { if (fs > 0) cwarn << "Missing parameter"; } - else { + else + { u256 endowment = atoll(fields[0].c_str()); u256 gas = atoll(fields[2].c_str()); u256 gasPrice = atoll(fields[1].c_str()); @@ -958,7 +963,7 @@ vector form_dialog(vector _sv, vector _lv, vector form_dialog(vector _sv, vector _lv, vector form_dialog(vector _sv, vector _lv, vector Date: Mon, 7 Apr 2014 21:04:26 -0400 Subject: [PATCH 4/5] curly curly --- eth/main.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/eth/main.cpp b/eth/main.cpp index 7c5f51be4..e1eba9f44 100644 --- a/eth/main.cpp +++ b/eth/main.cpp @@ -576,7 +576,8 @@ int main(int argc, char** argv) string sechex = fields[4]; string sdata = fields[5]; int ssize = fields[4].length(); - if (size < 40) { + if (size < 40) + { if (size > 0) cwarn << "Invalid address length: " << size; } @@ -621,7 +622,8 @@ int main(int argc, char** argv) fields[0].erase(std::remove(fields[0].begin(), fields[0].end(), ' '), fields[0].end()); int size = fields[0].length(); u256 amount = atoll(fields[1].c_str()); - if (size < 40) { + if (size < 40) + { if (size > 0) cwarn << "Invalid address length: " << size; } From 3791926e97227ef32143e1f8cc0cea120608e957 Mon Sep 17 00:00:00 2001 From: Marko Simovic Date: Tue, 8 Apr 2014 01:32:00 -0400 Subject: [PATCH 5/5] Updated to allow listening+UPnP on system-assigned port --- libethereum/Client.cpp | 3 ++- libethereum/PeerServer.cpp | 19 ++++++++++++++ libethereum/PeerServer.h | 3 +++ test/network.cpp | 51 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 75 insertions(+), 1 deletion(-) create mode 100644 test/network.cpp diff --git a/libethereum/Client.cpp b/libethereum/Client.cpp index 9c50e7e83..eea3edf76 100644 --- a/libethereum/Client.cpp +++ b/libethereum/Client.cpp @@ -99,7 +99,8 @@ void Client::startNetwork(unsigned short _listenPort, std::string const& _seedHo catch (std::exception const&) { // Probably already have the port open. - m_net.reset(new PeerServer(m_clientVersion, m_bc, 0, _mode)); + cwarn << "Could not initialize with specified/default port. Trying system-assigned port"; + m_net.reset(new PeerServer(m_clientVersion, m_bc, 0, _mode, _publicIP, _upnp)); } m_net->setIdealPeerCount(_peers); diff --git a/libethereum/PeerServer.cpp b/libethereum/PeerServer.cpp index e16bae671..b4ff3890e 100644 --- a/libethereum/PeerServer.cpp +++ b/libethereum/PeerServer.cpp @@ -71,6 +71,25 @@ PeerServer::PeerServer(std::string const& _clientVersion, BlockChain const& _ch, clog(NetNote) << "Id:" << toHex(m_key.address().ref().cropped(0, 4)) << "Mode: " << (_m == NodeMode::PeerServer ? "PeerServer" : "Full"); } +PeerServer::PeerServer(std::string const& _clientVersion, BlockChain const& _ch, unsigned int _networkId, NodeMode _m, string const& _publicAddress, bool _upnp): + m_clientVersion(_clientVersion), + m_mode(_m), + m_listenPort(0), + m_chain(&_ch), + m_acceptor(m_ioService, bi::tcp::endpoint(bi::tcp::v4(), 0)), + m_socket(m_ioService), + m_key(KeyPair::create()), + m_networkId(_networkId) +{ + m_listenPort = m_acceptor.local_endpoint().port(); + + // populate addresses. + populateAddresses(); + determinePublic(_publicAddress, _upnp); + ensureAccepting(); + clog(NetNote) << "Id:" << toHex(m_key.address().ref().cropped(0, 4)) << "Mode: " << (m_mode == NodeMode::PeerServer ? "PeerServer" : "Full"); +} + PeerServer::PeerServer(std::string const& _clientVersion, BlockChain const& _ch, unsigned int _networkId, NodeMode _m): m_clientVersion(_clientVersion), m_mode(_m), diff --git a/libethereum/PeerServer.h b/libethereum/PeerServer.h index cc877300e..425f262a9 100644 --- a/libethereum/PeerServer.h +++ b/libethereum/PeerServer.h @@ -42,8 +42,11 @@ class PeerServer public: /// Start server, listening for connections on the given port. PeerServer(std::string const& _clientVersion, BlockChain const& _ch, unsigned int _networkId, unsigned short _port, NodeMode _m = NodeMode::Full, std::string const& _publicAddress = std::string(), bool _upnp = true); + /// Start server, listening for connections on a system-assigned port. + PeerServer(std::string const& _clientVersion, BlockChain const& _ch, unsigned int _networkId, NodeMode _m = NodeMode::Full, std::string const& _publicAddress = std::string(), bool _upnp = true); /// Start server, but don't listen. PeerServer(std::string const& _clientVersion, BlockChain const& _ch, unsigned int _networkId, NodeMode _m = NodeMode::Full); + ~PeerServer(); static unsigned protocolVersion(); diff --git a/test/network.cpp b/test/network.cpp new file mode 100644 index 000000000..3e27ac6b9 --- /dev/null +++ b/test/network.cpp @@ -0,0 +1,51 @@ +/* + This file is part of cpp-ethereum. + + cpp-ethereum is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + cpp-ethereum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with cpp-ethereum. If not, see . +*/ +/** @file network.cpp + * @author Marko Simovic + * @date 2014 + * Basic networking tests + */ + +#include +#include +#include +#include +#include +#include "TestHelper.h" +using namespace std; +using namespace eth; + +BOOST_AUTO_TEST_CASE(listen_port_busy) +{ + short port = 20000; + + //make use of the port ahead of our client + ba::io_service ioService; + bi::tcp::endpoint endPoint(bi::tcp::v4(), port); + bi::tcp::acceptor acceptor(ioService, endPoint); + acceptor.listen(10); + + //prepare client and try to listen on same, used, port + Client c1("TestClient1", KeyPair::create().address(), + (boost::filesystem::temp_directory_path() / boost::filesystem::unique_path()).string()); + + c1.startNetwork(port); + + BOOST_REQUIRE(c1.haveNetwork()); + BOOST_REQUIRE(c1.peerServer()->listenPort() != 0); + BOOST_REQUIRE(c1.peerServer()->listenPort() != port); +}