Browse Source

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

cl-refactor
Gav Wood 10 years ago
parent
commit
148515ecc6
  1. 26
      libp2p/Common.cpp
  2. 9
      libp2p/Common.h
  3. 8
      libp2p/Host.cpp
  4. 48
      libp2p/NodeTable.cpp
  5. 15
      libp2p/RLPxHandshake.cpp
  6. 21
      mix/ClientModel.cpp
  7. 16
      mix/ContractCallDataEncoder.cpp
  8. 6
      mix/DebuggingStateWrapper.h
  9. 10
      mix/MixClient.cpp
  10. 20
      mix/qml/CodeEditorView.qml
  11. 25
      mix/qml/LogsPane.qml
  12. 1
      mix/qml/QHashTypeView.qml
  13. 1
      mix/qml/QIntTypeView.qml
  14. 1
      mix/qml/QStringTypeView.qml
  15. 5
      mix/qml/StatusPane.qml
  16. 11
      mix/qml/StructView.qml
  17. 5
      mix/qml/WebCodeEditor.qml
  18. 6
      mix/qml/html/WebContainer.html
  19. 61
      mix/qml/html/cm/anyword-hint.js
  20. 34
      mix/qml/html/cm/show-hint.css
  21. 12
      mix/qml/html/cm/solarized.css
  22. 12
      mix/qml/html/cm/solidityToken.js
  23. 16
      mix/qml/html/codeeditor.js
  24. 6
      neth/main.cpp
  25. 38
      test/net.cpp

26
libp2p/Common.cpp

@ -26,6 +26,16 @@ using namespace dev::p2p;
const unsigned dev::p2p::c_protocolVersion = 3;
bool p2p::isPublicAddress(std::string const& _addressToCheck)
{
return isPublicAddress(bi::address::from_string(_addressToCheck));
}
bool p2p::isPublicAddress(bi::address const& _addressToCheck)
{
return !(isPrivateAddress(_addressToCheck) || isLocalHostAddress(_addressToCheck));
}
// Helper function to determine if an address falls within one of the reserved ranges
// For V4:
// Class A "10.*", Class B "172.[16->31].*", Class C "192.168.*"
@ -55,6 +65,11 @@ bool p2p::isPrivateAddress(bi::address const& _addressToCheck)
return false;
}
bool p2p::isPrivateAddress(std::string const& _addressToCheck)
{
return isPrivateAddress(bi::address::from_string(_addressToCheck));
}
// Helper function to determine if an address is localhost
bool p2p::isLocalHostAddress(bi::address const& _addressToCheck)
{
@ -69,6 +84,11 @@ bool p2p::isLocalHostAddress(bi::address const& _addressToCheck)
return find(c_rejectAddresses.begin(), c_rejectAddresses.end(), _addressToCheck) != c_rejectAddresses.end();
}
bool p2p::isLocalHostAddress(std::string const& _addressToCheck)
{
return isLocalHostAddress(bi::address::from_string(_addressToCheck));
}
std::string p2p::reasonOf(DisconnectReason _r)
{
switch (_r)
@ -89,3 +109,9 @@ std::string p2p::reasonOf(DisconnectReason _r)
default: return "Unknown reason.";
}
}
void Node::cullEndpoint()
{
if (!isPublicAddress(endpoint.tcp.address()) && isPublicAddress(endpoint.udp.address()))
endpoint.tcp.address(endpoint.udp.address());
}

9
libp2p/Common.h

@ -54,7 +54,11 @@ extern const unsigned c_protocolVersion;
using NodeId = h512;
bool isPrivateAddress(bi::address const& _addressToCheck);
bool isPrivateAddress(std::string const& _addressToCheck);
bool isLocalHostAddress(bi::address const& _addressToCheck);
bool isLocalHostAddress(std::string const& _addressToCheck);
bool isPublicAddress(bi::address const& _addressToCheck);
bool isPublicAddress(std::string const& _addressToCheck);
class UPnP;
class Capability;
@ -62,6 +66,8 @@ class Host;
class Session;
struct NetworkStartRequired: virtual dev::Exception {};
struct InvalidPublicIPAddress: virtual dev::Exception {};
struct InvalidHostIPAddress: virtual dev::Exception {};
struct NetWarn: public LogChannel { static const char* name() { return "!N!"; } static const int verbosity = 0; };
struct NetNote: public LogChannel { static const char* name() { return "*N*"; } static const int verbosity = 1; };
@ -169,6 +175,9 @@ struct Node
virtual NodeId const& address() const { return id; }
virtual Public const& publicKey() const { return id; }
/// Adopt UDP address for TCP if TCP isn't public and UDP is. (to be removed when protocol is updated for nat)
void cullEndpoint();
NodeId id;
/// Endpoints by which we expect to reach node.

8
libp2p/Host.cpp

@ -592,12 +592,12 @@ void Host::startedWorking()
m_run = true;
}
// try to open acceptor (todo: ipv6)
m_listenPort = Network::tcp4Listen(m_tcp4Acceptor, m_netPrefs.listenPort);
// start capability threads
// start capability threads (ready for incoming connections)
for (auto const& h: m_capabilities)
h.second->onStarting();
// try to open acceptor (todo: ipv6)
m_listenPort = Network::tcp4Listen(m_tcp4Acceptor, m_netPrefs.listenPort);
// determine public IP, but only if we're able to listen for connections
// todo: GUI when listen is unavailable in UI

48
libp2p/NodeTable.cpp

@ -70,25 +70,22 @@ shared_ptr<NodeEntry> NodeTable::addNode(Public const& _pubk, bi::udp::endpoint
shared_ptr<NodeEntry> NodeTable::addNode(Node const& _node)
{
if (_node.endpoint.udp.address().to_string() == "0.0.0.0" || _node.endpoint.tcp.address().to_string() == "0.0.0.0")
// re-enable tcp checks when NAT hosts are handled by discover
// we handle when tcp endpoint is 0 below
if (_node.endpoint.udp.address().to_string() == "0.0.0.0")
{
string ptype;
if (_node.endpoint.udp.address().to_string() != "0.0.0.0")
ptype = "TCP";
else if (_node.endpoint.tcp.address().to_string() != "0.0.0.0")
ptype = "UDP";
else
ptype = "TCP,UDP";
clog(NodeTableWarn) << "addNode Failed. Invalid" << ptype << "address 0.0.0.0 for" << _node.id.abridged();
clog(NodeTableWarn) << "addNode Failed. Invalid UDP address 0.0.0.0 for" << _node.id.abridged();
return move(shared_ptr<NodeEntry>());
}
// ping address if nodeid is empty
// ping address to recover nodeid if nodeid is empty
if (!_node.id)
{
clog(NodeTableConnect) << "Sending public key discovery Ping to" << _node.endpoint.udp << "(Advertising:" << m_node.endpoint.udp << ")";
m_pubkDiscoverPings[_node.endpoint.udp.address()] = std::chrono::steady_clock::now();
{
Guard l(x_pubkDiscoverPings);
m_pubkDiscoverPings[_node.endpoint.udp.address()] = std::chrono::steady_clock::now();
}
PingNode p(_node.endpoint.udp, m_node.endpoint.udp.address().to_string(), m_node.endpoint.udp.port());
p.sign(m_secret);
m_socketPointer->send(p);
@ -103,6 +100,7 @@ shared_ptr<NodeEntry> NodeTable::addNode(Node const& _node)
shared_ptr<NodeEntry> ret(new NodeEntry(m_node, _node.id, NodeIPEndpoint(_node.endpoint.udp, _node.endpoint.tcp)));
m_nodes[_node.id] = ret;
ret->cullEndpoint();
PingNode p(_node.endpoint.udp, m_node.endpoint.udp.address().to_string(), m_node.endpoint.udp.port());
p.sign(m_secret);
m_socketPointer->send(p);
@ -314,10 +312,9 @@ void NodeTable::noteActiveNode(Public const& _pubk, bi::udp::endpoint const& _en
if (!!node && !node->pending)
{
clog(NodeTableConnect) << "Noting active node:" << _pubk.abridged() << _endpoint.address().to_string() << ":" << _endpoint.port();
// update udp endpoint
node->endpoint.udp.address(_endpoint.address());
node->endpoint.udp.port(_endpoint.port());
node->cullEndpoint();
shared_ptr<NodeEntry> contested;
{
@ -399,7 +396,7 @@ void NodeTable::onReceived(UDPSocketFace*, bi::udp::endpoint const& _from, bytes
bytesConstRef signedBytes(hashedBytes.cropped(Signature::size, hashedBytes.size() - Signature::size));
// todo: verify sig via known-nodeid and MDC, or, do ping/pong auth if node/endpoint is unknown/untrusted
// todo: verify sig via known-nodeid and MDC
bytesConstRef sigBytes(_packet.cropped(h256::size, Signature::size));
Public nodeid(dev::recover(*(Signature const*)sigBytes.data(), sha3(signedBytes)));
@ -430,8 +427,7 @@ void NodeTable::onReceived(UDPSocketFace*, bi::udp::endpoint const& _from, bytes
dropNode(n);
if (auto n = nodeEntry(it->first.first))
if (m_nodeEventHandler && n->pending)
n->pending = false;
n->pending = false;
it = m_evictions.erase(it);
}
@ -441,14 +437,18 @@ void NodeTable::onReceived(UDPSocketFace*, bi::udp::endpoint const& _from, bytes
{
if (auto n = nodeEntry(nodeid))
n->pending = false;
else if (m_pubkDiscoverPings.count(_from.address()))
{
{
Guard l(x_pubkDiscoverPings);
m_pubkDiscoverPings.erase(_from.address());
}
if (!haveNode(nodeid))
addNode(nodeid, _from, bi::tcp::endpoint(_from.address(), _from.port()));
}
else
return; // unsolicited pong; don't note node as active
}
else if (m_pubkDiscoverPings.count(_from.address()))
{
m_pubkDiscoverPings.erase(_from.address());
addNode(nodeid, _from, bi::tcp::endpoint(_from.address(), _from.port()));
}
else
return; // unsolicited pong; don't note node as active
break;
}

15
libp2p/RLPxHandshake.cpp

@ -131,7 +131,14 @@ void RLPXHandshake::readAck()
void RLPXHandshake::error()
{
clog(NetConnect) << "Disconnecting " << m_socket->remoteEndpoint() << " (Handshake Failed)";
m_idleTimer.cancel();
auto connected = m_socket->isConnected();
if (connected && !m_socket->remoteEndpoint().address().is_unspecified())
clog(NetConnect) << "Disconnecting " << m_socket->remoteEndpoint() << " (Handshake Failed)";
else
clog(NetConnect) << "Handshake Failed (Connection reset by peer)";
m_socket->close();
if (m_io != nullptr)
delete m_io;
@ -140,7 +147,10 @@ void RLPXHandshake::error()
void RLPXHandshake::transition(boost::system::error_code _ech)
{
if (_ech || m_nextState == Error || m_cancel)
{
clog(NetConnect) << "Handshake Failed (I/O Error:" << _ech.message() << ")";
return error();
}
auto self(shared_from_this());
if (m_nextState == New)
@ -265,7 +275,8 @@ void RLPXHandshake::transition(boost::system::error_code _ech)
{
if (!_ec)
{
clog(NetWarn) << "Disconnecting " << m_socket->remoteEndpoint() << " (Handshake Timeout)";
if (!m_socket->remoteEndpoint().address().is_unspecified())
clog(NetWarn) << "Disconnecting " << m_socket->remoteEndpoint() << " (Handshake Timeout)";
cancel();
}
});

21
mix/ClientModel.cpp

@ -242,7 +242,12 @@ void ClientModel::executeSequence(std::vector<TransactionSettings> const& _seque
break;
}
if (!f)
BOOST_THROW_EXCEPTION(FunctionNotFoundException() << FunctionName(transaction.functionId.toStdString()));
{
emit runFailed("Function '" + transaction.functionId + tr("' not found. Please check transactions or the contract code."));
m_running = false;
emit runStateChanged();
return;
}
if (!transaction.functionId.isEmpty())
encoder.encode(f);
for (QVariableDeclaration const* p: f->parametersList())
@ -269,7 +274,12 @@ void ClientModel::executeSequence(std::vector<TransactionSettings> const& _seque
{
auto contractAddressIter = m_contractAddresses.find(transaction.contractId);
if (contractAddressIter == m_contractAddresses.end())
BOOST_THROW_EXCEPTION(dev::Exception() << dev::errinfo_comment("Contract not deployed: " + transaction.contractId.toStdString()));
{
emit runFailed("Contract '" + transaction.contractId + tr(" not deployed.") + "' " + tr(" Cannot call ") + transaction.functionId);
m_running = false;
emit runStateChanged();
return;
}
callContract(contractAddressIter->second, encoder.encodedData(), transaction);
}
}
@ -283,7 +293,6 @@ void ClientModel::executeSequence(std::vector<TransactionSettings> const& _seque
std::cerr << boost::current_exception_diagnostic_information();
emit runFailed(QString::fromStdString(boost::current_exception_diagnostic_information()));
}
catch(std::exception const& e)
{
std::cerr << boost::current_exception_diagnostic_information();
@ -376,6 +385,8 @@ void ClientModel::showDebuggerForTransaction(ExecutionResult const& _t)
for(auto l: solLocals)
if (l.first < (int)s.stack.size())
{
if (l.second->type()->name().startsWith("mapping"))
break; //mapping type not yet managed
localDeclarations.push_back(QVariant::fromValue(l.second));
localValues[l.second->name()] = formatValue(l.second->type()->type(), s.stack[l.first]);
}
@ -400,6 +411,8 @@ void ClientModel::showDebuggerForTransaction(ExecutionResult const& _t)
storageDec = new QVariableDeclaration(debugData, storageIter.value().name.toStdString(), storageIter.value().type);
storageDeclarations[storageDec->name()] = storageDec;
}
if (storageDec->type()->name().startsWith("mapping"))
break; //mapping type not yet managed
storageDeclarationList.push_back(QVariant::fromValue(storageDec));
storageValues[storageDec->name()] = formatValue(storageDec->type()->type(), st.second);
}
@ -408,7 +421,7 @@ void ClientModel::showDebuggerForTransaction(ExecutionResult const& _t)
storage["values"] = storageValues;
prevInstructionIndex = instructionIndex;
solState = new QSolState(debugData, std::move(storage), std::move(solCallStack), std::move(locals), instruction.getLocation().start, instruction.getLocation().end);
solState = new QSolState(debugData, std::move(storage), std::move(solCallStack), std::move(locals), instruction.getLocation().start, instruction.getLocation().end, QString::fromUtf8(instruction.getLocation().sourceName->c_str()));
}
states.append(QVariant::fromValue(new QMachineState(debugData, instructionIndex, s, codes[s.codeIndex], data[s.dataIndex], solState)));

16
mix/ContractCallDataEncoder.cpp

@ -76,18 +76,22 @@ unsigned ContractCallDataEncoder::encodeSingleItem(QVariant const& _data, Solidi
unsigned const alignSize = 32;
QString src = _data.toString();
bytes result;
if (src.length() >= 2 && ((src.startsWith("\"") && src.endsWith("\"")) || (src.startsWith("\'") && src.endsWith("\'"))))
{
if ((src.startsWith("\"") && src.endsWith("\"")) || (src.startsWith("\'") && src.endsWith("\'")))
src = src.remove(src.length() - 1, 1).remove(0, 1);
QByteArray bytesAr = src.toLocal8Bit();
result = bytes(bytesAr.begin(), bytesAr.end());
}
else if (src.startsWith("0x"))
QRegExp rx("[a-z]+");
if (src.startsWith("0x"))
{
result = fromHex(src.toStdString().substr(2));
if (_type.type != SolidityType::Type::Bytes)
result = padded(result, alignSize);
}
else if (rx.indexIn(src.toLower(), 0) != -1)
{
QByteArray bytesAr = src.toLocal8Bit();
result = bytes(bytesAr.begin(), bytesAr.end());
}
else
{
bigint i(src.toStdString());

6
mix/DebuggingStateWrapper.h

@ -65,10 +65,11 @@ class QSolState: public QObject
Q_PROPERTY(QVariantMap locals MEMBER m_locals CONSTANT)
Q_PROPERTY(int start MEMBER m_start CONSTANT)
Q_PROPERTY(int end MEMBER m_end CONSTANT)
Q_PROPERTY(QString sourceName MEMBER m_sourceName CONSTANT)
public:
QSolState(QObject* _parent, QVariantMap&& _storage, QVariantList&& _callStack, QVariantMap&& _locals, int _start, int _end):
QObject(_parent), m_storage(_storage), m_callStack(_callStack), m_locals(_locals), m_start(_start), m_end(_end)
QSolState(QObject* _parent, QVariantMap&& _storage, QVariantList&& _callStack, QVariantMap&& _locals, int _start, int _end, QString _sourceName):
QObject(_parent), m_storage(_storage), m_callStack(_callStack), m_locals(_locals), m_start(_start), m_end(_end), m_sourceName(_sourceName)
{ }
private:
@ -77,6 +78,7 @@ private:
QVariantMap m_locals;
int m_start;
int m_end;
QString m_sourceName;
};
/**

10
mix/MixClient.cpp

@ -44,7 +44,7 @@ namespace mix
const Secret c_defaultUserAccountSecret = Secret("cb73d9408c4720e230387d956eb0f829d8a4dd2c1055f96257167e14e7169074");
const u256 c_mixGenesisDifficulty = c_minimumDifficulty; //TODO: make it lower for Mix somehow
bytes MixBlockChain::createGenesisBlock(h256 _stateRoot)
{
RLPStream block(3);
@ -80,6 +80,7 @@ void MixClient::resetState(std::map<Secret, u256> _accounts)
SecureTrieDB<Address, MemoryDB> accountState(&m_stateDB);
accountState.init();
m_userAccounts.clear();
std::map<Address, Account> genesisState;
for (auto account: _accounts)
{
@ -260,8 +261,8 @@ Address MixClient::submitTransaction(Secret _secret, u256 _endowment, bytes cons
dev::eth::ExecutionResult MixClient::call(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber)
{
State temp = asOf(_blockNumber);
(void)_blockNumber;
State temp = asOf(eth::PendingBlock);
u256 n = temp.transactionsFrom(toAddress(_secret));
Transaction t(_value, _gasPrice, _gas, _dest, _data, n, _secret);
bytes rlp = t.rlp();
@ -272,11 +273,12 @@ dev::eth::ExecutionResult MixClient::call(Secret _secret, u256 _value, Address _
dev::eth::ExecutionResult MixClient::create(Secret _secret, u256 _value, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber)
{
(void)_blockNumber;
u256 n;
State temp;
{
ReadGuard lr(x_state);
temp = asOf(_blockNumber);
temp = asOf(eth::PendingBlock);
n = temp.transactionsFrom(toAddress(_secret));
}
Transaction t(_value, _gasPrice, _gas, _data, n, _secret);

20
mix/qml/CodeEditorView.qml

@ -67,10 +67,26 @@ Item {
return null;
}
function highlightExecution(documentId, location) {
function highlightExecution(documentId, location)
{
var editor = getEditor(documentId);
if (editor)
editor.highlightExecution(location);
{
if (documentId !== location.sourceName)
findAndHightlight(location.start, location.end, location.sourceName)
else
editor.highlightExecution(location);
}
}
// Execution is not in the current document. Try:
// Open targeted document and hightlight (TODO) or
// Warn user that file is not available
function findAndHightlight(start, end, sourceName)
{
var editor = getEditor(currentDocumentId);
if (editor)
editor.showWarning(qsTr("Currently debugging in " + sourceName + ". Source not available."));
}
function editingContract() {

25
mix/qml/LogsPane.qml

@ -153,31 +153,6 @@ Rectangle
}
}
ToolButton {
id: compilationButton
checkable: true
height: LogsPaneStyle.generic.layout.headerButtonHeight
anchors.verticalCenter: parent.verticalCenter
checked: false
onCheckedChanged: {
proxyModel.toogleFilter("compilation")
}
tooltip: qsTr("Compilation")
style:
ButtonStyle {
label:
Item {
DefaultLabel {
font.family: LogsPaneStyle.generic.layout.logLabelFont
font.pointSize: Style.absoluteSize(-3)
color: "#5391d8"
anchors.centerIn: parent
text: qsTr("Compilation")
}
}
}
}
DefaultTextField
{
id: searchBox

1
mix/qml/QHashTypeView.qml

@ -15,7 +15,6 @@ Item
Rectangle {
anchors.fill: parent
radius: 4
color: "#f7f7f7"
TextInput {
id: textinput
text: value

1
mix/qml/QIntTypeView.qml

@ -16,7 +16,6 @@ Item
Rectangle {
anchors.fill: parent
radius: 4
color: "#f7f7f7"
TextInput {
id: textinput
text: value

1
mix/qml/QStringTypeView.qml

@ -15,7 +15,6 @@ Item
Rectangle {
anchors.fill: parent
radius: 4
color: "#f7f7f7"
TextInput {
id: textinput
text: value

5
mix/qml/StatusPane.qml

@ -24,7 +24,6 @@ Rectangle {
var errorInfo = ErrorLocationFormater.extractErrorInfo(message, true);
status.text = errorInfo.errorLocation + " " + errorInfo.errorDetail;
debugImg.state = "";
errorMessage(status.text, "Compilation");
}
debugRunActionIcon.enabled = codeModel.hasContract;
}
@ -77,9 +76,9 @@ Rectangle {
function format(_message)
{
var formatted = _message.match(/(?:<dev::eth::)(.+)(?:>)/);
if (formatted === null)
if (formatted)
formatted = _message.match(/(?:<dev::)(.+)(?:>)/);
if (formatted.length > 1)
if (formatted && formatted.length > 1)
formatted = formatted[1];
else
return _message;

11
mix/qml/StructView.qml

@ -24,24 +24,24 @@ Column
height: 20
id: typeLabel
text: modelData.type.name
Layout.preferredWidth: 60
anchors.verticalCenter: parent.verticalCenter
}
DefaultLabel {
id: nameLabel
text: modelData.name
Layout.preferredWidth: 100
anchors.verticalCenter: parent.verticalCenter
}
DefaultLabel {
id: equalLabel
text: "="
Layout.preferredWidth: 15
anchors.verticalCenter: parent.verticalCenter
}
Loader
{
id: typeLoader
Layout.preferredWidth: 150
anchors.verticalCenter: parent.verticalCenter
sourceComponent:
{
var t = modelData.type.category;
@ -63,7 +63,8 @@ Column
var ptype = members[index].type;
var pname = members[index].name;
var vals = value;
if (ptype.category === QSolidityType.Struct && !item.members) {
if (ptype.category === QSolidityType.Struct && !item.members)
{
item.value = getValue();
item.members = ptype.members;
}

5
mix/qml/WebCodeEditor.qml

@ -45,6 +45,11 @@ Item {
editorBrowser.runJavaScript("highlightExecution(" + location.start + "," + location.end + ")");
}
function showWarning(content) {
if (initialized)
editorBrowser.runJavaScript("showWarning('" + content + "')");
}
function getBreakpoints() {
return currentBreakpoints;
}

6
mix/qml/html/WebContainer.html

@ -23,9 +23,9 @@ updateContracts = function(contracts) {
var contractProto = window.web3.eth.contract(contracts[c].interface);
var contract = new contractProto(contracts[c].address);
window.contracts[c] = {
address: c.address,
interface: c.interface,
contract: contract,
address: contracts[c].address,
interface: contracts[c].interface,
contract: contract
};
}
}

61
mix/qml/html/cm/anyword-hint.js

@ -13,6 +13,18 @@
var curWord = start != end && curLine.slice(start, end);
var list = [], seen = {};
if (editor.getMode().name === "solidity")
{
list = addSolToken(curWord, list, seen, solCurrency(), solCurrency);
list = addSolToken(curWord, list, seen, solKeywords(), solKeywords);
list = addSolToken(curWord, list, seen, solStdContract(), solStdContract);
list = addSolToken(curWord, list, seen, solTime(), solTime);
list = addSolToken(curWord, list, seen, solTypes(), solTypes);
list = addSolToken(curWord, list, seen, solMisc(), solMisc);
}
var previousWord = "";
var re = new RegExp(word.source, "g");
for (var dir = -1; dir <= 1; dir += 2) {
var line = cur.line, endLine = Math.min(Math.max(line + dir * range, editor.firstLine()), editor.lastLine()) + dir;
@ -22,41 +34,60 @@
if (line == cur.line && m[0] === curWord) continue;
if ((!curWord || m[0].lastIndexOf(curWord, 0) === 0) && !Object.prototype.hasOwnProperty.call(seen, m[0])) {
seen[m[0]] = true;
list.push({ text: m[0] });
var w = { text: m[0] };
checkDeclaration(previousWord, "Contract", w);
checkDeclaration(previousWord, "Function", w);
list.push(w);
}
previousWord = m[0];
}
}
}
if (editor.getMode().name === "solidity")
{
list = addSolToken(curWord, list, solCurrency(), solCurrency);
list = addSolToken(curWord, list, solKeywords(), solKeywords);
list = addSolToken(curWord, list, solStdContract(), solStdContract);
list = addSolToken(curWord, list, solTime(), solTime);
list = addSolToken(curWord, list, solTypes(), solTypes);
list = addSolToken(curWord, list, solMisc(), solMisc);
}
return {list: list, from: CodeMirror.Pos(cur.line, start), to: CodeMirror.Pos(cur.line, end)};
});
})();
function addSolToken(curWord, list, tokens, type)
function addSolToken(curWord, list, seen, tokens, type)
{
var keywordsTypeName = keywordsName();
for (var key in tokens)
{
seen[key] = true;
if (curWord === false || key.indexOf(curWord, 0) === 0)
{
var token = { text: key };
token.render = function(elt, data, cur)
{
elt.className = elt.className + " " + type.name.toLowerCase();
elt.appendChild(document.createTextNode(cur.displayText || cur.text));
render(elt, data, cur, type.name.toLowerCase(), keywordsTypeName[type.name.toLowerCase()]);
}
list.push(token);
}
}
return list;
}
function render(elt, data, cur, csstype, type)
{
var container = document.createElement("div");
var word = document.createElement("div");
word.className = csstype + " solToken";
word.appendChild(document.createTextNode(cur.displayText || cur.text));
var typeDiv = document.createElement("type");
typeDiv.appendChild(document.createTextNode(type));
typeDiv.className = "solTokenType";
container.appendChild(word);
container.appendChild(typeDiv);
elt.appendChild(container);
}
function checkDeclaration(previousToken, target, current)
{
if (previousToken.toLowerCase() === target.toLowerCase())
{
current.render = function(elt, data, cur)
{
render(elt, data, cur, "sol" + target, target);
}
}
}

34
mix/qml/html/cm/show-hint.css

@ -31,33 +31,29 @@
white-space: pre;
color: black;
cursor: pointer;
padding-left: 20px;
padding-top: 3px;
padding-bottom: 3px;
}
.CodeMirror-hint-active {
background: #4a90e2;
color: white;
color: white !important;
}
.solcurrency {
color: red;
.CodeMirror-hint-active .solToken,
.CodeMirror-hint-active .solTokenType
{
color: white !important;
}
.solkeywords {
color: brown;
.solToken {
float: left;
}
.solstdcontract {
color: blue;
}
.soltime {
color: green;
}
.soltypes {
color: orange;
}
.solMisc {
color: grey;
.solTokenType
{
font-style: italic;
color: #808080;
float: right;
}

12
mix/qml/html/cm/solarized.css

@ -16,14 +16,14 @@ http://ethanschoonover.com/solarized/img/solarized-palette.png
.solarized.base1 { color: #93a1a1; }
.solarized.base2 { color: #eee8d5; }
.solarized.base3 { color: #fdf6e3; }
.solarized.solar-yellow { color: #b58900; }
.solarized.solar-orange { color: #cb4b16; }
.solarized.solar-yellow, .solcurrency { color: #b58900; }
.solarized.solar-orange, .solkeywords { color: #cb4b16; }
.solarized.solar-red { color: #dc322f; }
.solarized.solar-magenta { color: #d33682; }
.solarized.solar-magenta, .solstdcontract { color: #d33682; }
.solarized.solar-violet { color: #6c71c4; }
.solarized.solar-blue { color: #268bd2; }
.solarized.solar-cyan { color: #2aa198; }
.solarized.solar-green { color: #859900; }
.solarized.solar-blue, .soltime { color: #268bd2; }
.solarized.solar-cyan, .soltypes { color: #2aa198; }
.solarized.solar-green, .solMisc { color: #859900; }
/* Color scheme for code-mirror */

12
mix/qml/html/cm/solidityToken.js

@ -27,3 +27,15 @@ function solMisc()
{
return { "true": true, "false": true, "null": true };
}
function keywordsName()
{
var keywords = {};
keywords[solCurrency.name.toLowerCase()] = "Currency";
keywords[solKeywords.name.toLowerCase()] = "Keyword";
keywords[solStdContract.name.toLowerCase()] = "Contract";
keywords[solTime.name.toLowerCase()] = "Time";
keywords[solTypes.name.toLowerCase()] = "Type";
keywords[solMisc.name.toLowerCase()] = "Misc";
return keywords;
}

16
mix/qml/html/codeeditor.js

@ -134,6 +134,8 @@ highlightExecution = function(start, end) {
executionMark.clear();
if (start === 0 && end + 1 === editor.getValue().length)
return; // Do not hightlight the whole document.
if (debugWarning)
debugWarning.clear();
executionMark = editor.markText(editor.posFromIndex(start), editor.posFromIndex(end), { className: "CodeMirror-exechighlight" });
}
@ -148,6 +150,20 @@ isClean = function()
return editor.isClean(changeId);
}
var debugWarning = null;
showWarning = function(content)
{
if (executionMark)
executionMark.clear();
if (debugWarning)
debugWarning.clear();
var node = document.createElement("div");
node.id = "annotation"
node.innerHTML = content;
node.className = "CodeMirror-errorannotation-context";
debugWarning = editor.addLineWidget(0, node, { coverGutter: false, above: true });
}
var annotation = null;
var compilationCompleteBool = true;
compilationError = function(line, column, content)

6
neth/main.cpp

@ -1152,7 +1152,7 @@ int main(int argc, char** argv)
break;
}
#if ETH_FATDB
// Contracts and addresses
y = 1;
auto acs = c->addresses();
@ -1181,6 +1181,10 @@ int main(int argc, char** argv)
if (y > height * 3 / 5 - 4)
break;
}
#else
mvwaddnstr(contractswin, 1, x, "build with ETH_FATDB to list contracts", qwidth);
mvwaddnstr(addswin, 1, x, "build with ETH_FATDB to list addresses", width / 2 - 4);
#endif
// Peers
y = 1;

38
test/net.cpp

@ -145,7 +145,41 @@ public:
bool success = false;
};
BOOST_AUTO_TEST_CASE(badPingNodePacket)
BOOST_AUTO_TEST_CASE(isIPAddressType)
{
string wildcard = "0.0.0.0";
BOOST_REQUIRE(bi::address::from_string(wildcard).is_unspecified());
string empty = "";
BOOST_REQUIRE_THROW(bi::address::from_string(empty).is_unspecified(), std::exception);
string publicAddress192 = "192.169.0.0";
BOOST_REQUIRE(isPublicAddress(publicAddress192));
BOOST_REQUIRE(!isPrivateAddress(publicAddress192));
BOOST_REQUIRE(!isLocalHostAddress(publicAddress192));
string publicAddress172 = "172.32.0.0";
BOOST_REQUIRE(isPublicAddress(publicAddress172));
BOOST_REQUIRE(!isPrivateAddress(publicAddress172));
BOOST_REQUIRE(!isLocalHostAddress(publicAddress172));
string privateAddress192 = "192.168.1.0";
BOOST_REQUIRE(isPrivateAddress(privateAddress192));
BOOST_REQUIRE(!isPublicAddress(privateAddress192));
BOOST_REQUIRE(!isLocalHostAddress(privateAddress192));
string privateAddress172 = "172.16.0.0";
BOOST_REQUIRE(isPrivateAddress(privateAddress172));
BOOST_REQUIRE(!isPublicAddress(privateAddress172));
BOOST_REQUIRE(!isLocalHostAddress(privateAddress172));
string privateAddress10 = "10.0.0.0";
BOOST_REQUIRE(isPrivateAddress(privateAddress10));
BOOST_REQUIRE(!isPublicAddress(privateAddress10));
BOOST_REQUIRE(!isLocalHostAddress(privateAddress10));
}
BOOST_AUTO_TEST_CASE(v2PingNodePacket)
{
// test old versino of pingNode packet w/new
RLPStream s;
@ -153,7 +187,7 @@ BOOST_AUTO_TEST_CASE(badPingNodePacket)
PingNode p((bi::udp::endpoint()));
BOOST_REQUIRE_NO_THROW(p = PingNode::fromBytesConstRef(bi::udp::endpoint(), bytesConstRef(&s.out())));
BOOST_REQUIRE(p.version == 0);
BOOST_REQUIRE(p.version == 2);
}
BOOST_AUTO_TEST_CASE(test_neighbours_packet)

Loading…
Cancel
Save