Browse Source

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

Conflicts:
	libethereum/BlockQueue.cpp
cl-refactor
Gav Wood 10 years ago
parent
commit
00bf2aefc0
  1. 1
      .gitignore
  2. 6
      libevm/VM.cpp
  3. 2
      libevm/VM.h
  4. 82
      libwhisper/Message.cpp
  5. 2
      libwhisper/Message.h
  6. 2
      mix/ClientModel.cpp
  7. 30
      mix/CodeModel.cpp
  8. 65
      mix/CodeModel.h
  9. 19
      mix/qml/Application.qml
  10. 8
      mix/qml/html/cm/inkpot.css
  11. 31
      mix/qml/html/codeeditor.js
  12. 72
      test/libethereum/StateTestsFiller/stSpecialTestFiller.json
  13. 140
      test/libevm/VMTestsFiller/vmIOandFlowOperationsTestFiller.json
  14. 100
      test/libwhisper/whisperMessage.cpp

1
.gitignore

@ -35,6 +35,7 @@ build_xc
# build system
build.*/
extdep/install
extdep/download
*.pyc

6
libevm/VM.cpp

@ -71,7 +71,7 @@ bytesConstRef VM::go(ExtVMFace& _ext, OnOpFunc const& _onOp, uint64_t _steps)
for (unsigned i = 0; i < _ext.code.size(); ++i)
{
if (_ext.code[i] == (byte)Instruction::JUMPDEST)
m_jumpDests.insert(i);
m_jumpDests.push_back(i);
else if (_ext.code[i] >= (byte)Instruction::PUSH1 && _ext.code[i] <= (byte)Instruction::PUSH32)
i += _ext.code[i] - (unsigned)Instruction::PUSH1 + 1;
}
@ -546,7 +546,7 @@ bytesConstRef VM::go(ExtVMFace& _ext, OnOpFunc const& _onOp, uint64_t _steps)
break;
case Instruction::JUMP:
nextPC = m_stack.back();
if (!m_jumpDests.count(nextPC))
if (find(m_jumpDests.begin(), m_jumpDests.end(), (uint64_t)nextPC) == m_jumpDests.end() || nextPC > numeric_limits<uint64_t>::max() )
BOOST_THROW_EXCEPTION(BadJumpDestination());
m_stack.pop_back();
break;
@ -554,7 +554,7 @@ bytesConstRef VM::go(ExtVMFace& _ext, OnOpFunc const& _onOp, uint64_t _steps)
if (m_stack[m_stack.size() - 2])
{
nextPC = m_stack.back();
if (!m_jumpDests.count(nextPC))
if (find(m_jumpDests.begin(), m_jumpDests.end(), (uint64_t)nextPC) == m_jumpDests.end() || nextPC > numeric_limits<uint64_t>::max() )
BOOST_THROW_EXCEPTION(BadJumpDestination());
}
m_stack.pop_back();

2
libevm/VM.h

@ -74,7 +74,7 @@ private:
u256 m_curPC = 0;
bytes m_temp;
u256s m_stack;
std::set<u256> m_jumpDests;
std::vector<uint64_t> m_jumpDests;
std::function<void()> m_onFail;
bigint m_gas = 0;
};

82
libwhisper/Message.cpp

@ -35,34 +35,8 @@ Message::Message(Envelope const& _e, FullTopic const& _fk, Secret const& _s)
if (!decrypt(_s, &(_e.data()), b))
return;
else{}
else
{
// public - need to get the key through combining with the topic/topicIndex we know.
unsigned topicIndex = 0;
Secret topicSecret;
// determine topicSecret/topicIndex from knowledge of the collapsed topics (which give the order) and our full-size filter topic.
CollapsedTopic knownTopic = collapse(_fk);
for (unsigned ti = 0; ti < _fk.size() && !topicSecret; ++ti)
for (unsigned i = 0; i < _e.topic().size(); ++i)
if (_e.topic()[i] == knownTopic[ti])
{
topicSecret = _fk[ti];
topicIndex = i;
break;
}
if (_e.data().size() < _e.topic().size() * 32)
return;
// get key from decrypted topic key: just xor
h256 tk = h256(bytesConstRef(&(_e.data())).cropped(32 * topicIndex, 32));
bytesConstRef cipherText = bytesConstRef(&(_e.data())).cropped(32 * _e.topic().size());
// cdebug << "Decrypting(" << topicIndex << "): " << topicSecret << tk << (topicSecret ^ tk) << toHex(cipherText);
if (!decryptSym(topicSecret ^ tk, cipherText, b))
return;
// cdebug << "Got: " << toHex(b);
}
else if (!openBroadcastEnvelope(_e, _fk, b))
return;
if (populate(b))
if (_s)
@ -73,6 +47,34 @@ Message::Message(Envelope const& _e, FullTopic const& _fk, Secret const& _s)
}
}
bool Message::openBroadcastEnvelope(Envelope const& _e, FullTopic const& _fk, bytes& o_b)
{
// retrieve the key using the known topic and topicIndex.
unsigned topicIndex = 0;
Secret topicSecret;
// determine topicSecret/topicIndex from knowledge of the collapsed topics (which give the order) and our full-size filter topic.
CollapsedTopic knownTopic = collapse(_fk);
for (unsigned ti = 0; ti < _fk.size() && !topicSecret; ++ti)
for (unsigned i = 0; i < _e.topic().size(); ++i)
if (_e.topic()[i] == knownTopic[ti])
{
topicSecret = _fk[ti];
topicIndex = i;
break;
}
if (_e.data().size() < _e.topic().size() * h256::size)
return false;
unsigned index = topicIndex * 2;
h256 encryptedKey = h256(bytesConstRef(&(_e.data())).cropped(h256::size * index, h256::size));
h256 salt = h256(bytesConstRef(&(_e.data())).cropped(h256::size * ++index, h256::size));
h256 key = generateGamma(topicSecret, salt) ^ encryptedKey;
bytesConstRef cipherText = bytesConstRef(&(_e.data())).cropped(h256::size * 2 * _e.topic().size());
return decryptSym(key, cipherText, o_b);
}
bool Message::populate(bytes const& _data)
{
if (!_data.size())
@ -103,7 +105,7 @@ Envelope Message::seal(Secret _from, FullTopic const& _fullTopic, unsigned _ttl,
input[0] = 0;
memcpy(input.data() + 1, m_payload.data(), m_payload.size());
if (_from) // needs a sig
if (_from) // needs a signature
{
input.resize(1 + m_payload.size() + sizeof(Signature));
input[0] |= ContainsSignature;
@ -116,23 +118,19 @@ Envelope Message::seal(Secret _from, FullTopic const& _fullTopic, unsigned _ttl,
encrypt(m_to, &input, ret.m_data);
else
{
// create the shared secret and encrypt
// this message is for broadcast (could be read by anyone who knows at least one of the topics)
// create the shared secret for encrypting the payload, then encrypt the shared secret with each topic
Secret s = Secret::random();
for (h256 const& t: _fullTopic)
ret.m_data += (t ^ s).asBytes();
for (h256 const& t : _fullTopic)
{
h256 salt = h256::random();
ret.m_data += (generateGamma(t, salt) ^ s).asBytes();
ret.m_data += salt.asBytes();
}
bytes d;
encryptSym(s, &input, d);
ret.m_data += d;
for (unsigned i = 0; i < _fullTopic.size(); ++i)
{
bytes b;
h256 tk = h256(bytesConstRef(&(ret.m_data)).cropped(32 * i, 32));
bytesConstRef cipherText = bytesConstRef(&(ret.m_data)).cropped(32 * ret.topic().size());
cnote << "Test decrypting(" << i << "): " << _fullTopic[i] << tk << (_fullTopic[i] ^ tk) << toHex(cipherText);
assert(decryptSym(_fullTopic[i] ^ tk, cipherText, b));
cnote << "Got: " << toHex(b);
}
}
ret.proveWork(_workToProve);

2
libwhisper/Message.h

@ -127,6 +127,8 @@ public:
private:
bool populate(bytes const& _data);
bool openBroadcastEnvelope(Envelope const& _e, FullTopic const& _fk, bytes& o_b);
h256 generateGamma(h256 const& _key, h256 const& _salt) const { return sha3(_key ^ _salt); }
Public m_from;
Public m_to;

2
mix/ClientModel.cpp

@ -331,7 +331,7 @@ void ClientModel::executeSequence(vector<TransactionSettings> const& _sequence,
{
QSolidityType const* type = p->type();
QVariant value = transaction.parameterValues.value(p->name());
if (type->type().type == SolidityType::Type::Address)
if (type->type().type == SolidityType::Type::Address && value.toString().startsWith("<"))
{
std::pair<QString, int> ctrParamInstance = resolvePair(value.toString());
value = QVariant(resolveToken(ctrParamInstance, deployedContracts));

30
mix/CodeModel.cpp

@ -309,7 +309,7 @@ void CodeModel::runCompilationJob(int _jobId)
sourceNames.push_back(c.first.toStdString());
}
}
cs.compile(false);
cs.compile(m_optimizeCode);
gasEstimation(cs);
collectContracts(cs, sourceNames);
}
@ -380,7 +380,23 @@ void CodeModel::gasEstimation(solidity::CompilerStack const& _cs)
GasMeter::GasConsumption cost = gasItem->second;
std::stringstream v;
v << cost.value;
m_gasCostsMaps->push(sourceName, location.start, location.end, QString::fromStdString(v.str()), cost.isInfinite);
m_gasCostsMaps->push(sourceName, location.start, location.end, QString::fromStdString(v.str()), cost.isInfinite, GasMap::type::Statement);
}
if (contractDefinition.getConstructor() != nullptr)
{
GasMeter::GasConsumption cost = GasEstimator::functionalEstimation(*_cs.getRuntimeAssemblyItems(n), contractDefinition.getConstructor()->externalSignature());
std::stringstream v;
v << cost.value;
m_gasCostsMaps->push(sourceName, contractDefinition.getConstructor()->getLocation().start, contractDefinition.getConstructor()->getLocation().end, QString::fromStdString(v.str()), cost.isInfinite, GasMap::type::Constructor);
}
for (auto func: contractDefinition.getDefinedFunctions())
{
GasMeter::GasConsumption cost = GasEstimator::functionalEstimation(*_cs.getRuntimeAssemblyItems(n), func->externalSignature());
std::stringstream v;
v << cost.value;
m_gasCostsMaps->push(sourceName, func->getLocation().start, func->getLocation().end, QString::fromStdString(v.str()), cost.isInfinite, GasMap::type::Function);
}
}
}
@ -583,9 +599,15 @@ QString CodeModel::resolveFunctionName(dev::SourceLocation const& _location)
return QString();
}
void GasMapWrapper::push(QString _source, int _start, int _end, QString _value, bool _isInfinite)
void CodeModel::setOptimizeCode(bool _value)
{
m_optimizeCode = _value;
emit scheduleCompilationJob(++m_backgroundJobId);
}
void GasMapWrapper::push(QString _source, int _start, int _end, QString _value, bool _isInfinite, GasMap::type _type)
{
GasMap* gas = new GasMap(_start, _end, _value, _isInfinite, this);
GasMap* gas = new GasMap(_start, _end, _value, _isInfinite, _type, this);
m_gasMaps.find(_source).value().push_back(QVariant::fromValue(gas));
}

65
mix/CodeModel.h

@ -28,6 +28,7 @@
#include <QObject>
#include <QThread>
#include <QHash>
#include <QMetaEnum>
#include <libdevcore/Common.h>
#include <libdevcore/Guards.h>
#include <libevmasm/Assembly.h>
@ -130,39 +131,60 @@ struct SourceMap
using SourceMaps = QMap<QString, SourceMap>; //by source id
using GasCostsMaps = QMap<QString, QVariantList>; //gas cost by contract name
class GasMapWrapper: public QObject
{
Q_OBJECT
Q_PROPERTY(GasCostsMaps gasMaps MEMBER m_gasMaps CONSTANT)
public:
GasMapWrapper(QObject* _parent = nullptr): QObject(_parent){}
void push(QString _source, int _start, int _end, QString _value, bool _isInfinite);
bool contains(QString _key);
void insert(QString _source, QVariantList _variantList);
QVariantList gasCostsByDocId(QString _source);
private:
GasCostsMaps m_gasMaps;
};
class GasMap: public QObject
{
Q_OBJECT
Q_ENUMS(type)
Q_PROPERTY(int start MEMBER m_start CONSTANT)
Q_PROPERTY(int end MEMBER m_end CONSTANT)
Q_PROPERTY(QString gas MEMBER m_gas CONSTANT)
Q_PROPERTY(bool isInfinite MEMBER m_isInfinite CONSTANT)
Q_PROPERTY(QString codeBlockType READ codeBlockType CONSTANT)
public:
GasMap(int _start, int _end, QString _gas, bool _isInfinite, QObject* _parent): QObject(_parent), m_start(_start), m_end(_end), m_gas(_gas), m_isInfinite(_isInfinite) {}
enum type
{
Statement,
Function,
Constructor
};
GasMap(int _start, int _end, QString _gas, bool _isInfinite, type _type, QObject* _parent): QObject(_parent), m_start(_start), m_end(_end), m_gas(_gas), m_isInfinite(_isInfinite), m_type(_type) {}
int m_start;
int m_end;
QString m_gas;
bool m_isInfinite;
type m_type;
QString codeBlockType() const
{
QMetaEnum units = staticMetaObject.enumerator(staticMetaObject.indexOfEnumerator("type"));
if (m_type)
{
const char* key = units.valueToKey(m_type);
return QString(key).toLower();
}
return QString("");
}
};
class GasMapWrapper: public QObject
{
Q_OBJECT
Q_PROPERTY(GasCostsMaps gasMaps MEMBER m_gasMaps CONSTANT)
public:
GasMapWrapper(QObject* _parent = nullptr): QObject(_parent){}
void push(QString _source, int _start, int _end, QString _value, bool _isInfinite, GasMap::type _type);
bool contains(QString _key);
void insert(QString _source, QVariantList _variantList);
QVariantList gasCostsByDocId(QString _source);
private:
GasCostsMaps m_gasMaps;
};
/// Code compilation model. Compiles contracts in background an provides compiled contract data
@ -177,6 +199,7 @@ public:
Q_PROPERTY(QVariantMap contracts READ contracts NOTIFY codeChanged)
Q_PROPERTY(bool compiling READ isCompiling NOTIFY stateChanged)
Q_PROPERTY(bool hasContract READ hasContract NOTIFY codeChanged)
Q_PROPERTY(bool optimizeCode MEMBER m_optimizeCode WRITE setOptimizeCode)
/// @returns latest compilation results for contracts
QVariantMap contracts() const;
@ -209,6 +232,7 @@ public:
void gasEstimation(solidity::CompilerStack const& _cs);
/// Gas cost by doc id
Q_INVOKABLE QVariantList gasCostByDocumentId(QString const& _documentId) const;
Q_INVOKABLE void setOptimizeCode(bool _value);
signals:
/// Emited on compilation state change
@ -253,11 +277,10 @@ private:
std::map<QString, dev::bytes> m_compiledContracts; //by name
dev::Mutex x_pendingContracts;
std::map<QString, QString> m_pendingContracts; //name to source
bool m_optimizeCode = false;
friend class BackgroundWorker;
};
}
}
//Q_DECLARE_METATYPE(dev::mix::GasMap)

19
mix/qml/Application.qml

@ -119,6 +119,7 @@ ApplicationWindow {
Menu {
title: qsTr("Tools")
MenuItem { action: gasEstimationAction }
MenuItem { action: optimizeCodeAction }
}
Menu {
title: qsTr("Windows")
@ -419,9 +420,19 @@ ApplicationWindow {
text: qsTr("Display gas estimation")
shortcut: "Ctrl+G"
checkable: true
onTriggered:
{
mainContent.codeEditor.displayGasEstimation(checked);
}
onTriggered: mainContent.codeEditor.displayGasEstimation(checked);
}
Action {
id: optimizeCodeAction
text: qsTr("Enable optimized compilation")
shortcut: "Ctrl+Shift+O"
checkable: true
onTriggered: codeModel.setOptimizeCode(checked);
}
Settings {
property alias gasEstimation: gasEstimationAction.checked
property alias optimizeCode: optimizeCodeAction.checked
}
}

8
mix/qml/html/cm/inkpot.css

@ -68,3 +68,11 @@ span.CodeMirror-selectedtext { color: #ffffff !important; }
font-size: 12px;
}
.CodeMirror-gasCost
{
font-family: monospace;
font-size: 14px;
color: #409090;
text-shadow: none !important;
margin-left: 5px;
}

31
mix/qml/html/codeeditor.js

@ -210,9 +210,8 @@ setFontSize = function(size)
makeGasCostMarker = function(value) {
var marker = document.createElement("div");
marker.style.color = "#822";
marker.innerHTML = value;
marker.className = "CodeMirror-errorannotation-context";
marker.className = "CodeMirror-gasCost";
return marker;
};
@ -252,8 +251,23 @@ displayGasEstimation = function(show)
else
color = colorGradient[colorIndex];
var className = "CodeMirror-gasCosts" + i;
var line = editor.posFromIndex(gasCosts[i].start)
gasMarkText.push(editor.markText(line, editor.posFromIndex(gasCosts[i].end), { inclusiveLeft: true, inclusiveRight: true, handleMouseEvents: true, className: className, css: "background-color:" + color }));
var line = editor.posFromIndex(gasCosts[i].start);
var endChar;
if (gasCosts[i].codeBlockType === "statement" || gasCosts[i].codeBlockType === "")
{
endChar = editor.posFromIndex(gasCosts[i].end);
gasMarkText.push({ line: line, markText: editor.markText(line, endChar, { inclusiveLeft: true, inclusiveRight: true, handleMouseEvents: true, className: className, css: "background-color:" + color })});
}
else if (gasCosts[i].codeBlockType === "function" || gasCosts[i].codeBlockType === "constructor")
{
var l = editor.getLine(line.line);
endChar = { line: line.line, ch: line.ch + l.length };
var marker = document.createElement("div");
marker.innerHTML = " max execution cost: " + gasCosts[i].gas + " gas";
marker.className = "CodeMirror-gasCost";
editor.addWidget(endChar, marker, false, "over");
gasMarkText.push({ line: line.line, widget: marker });
}
gasMarkRef[className] = { line: line.line, value: gasCosts[i] };
}
}
@ -275,7 +289,12 @@ function clearGasMark()
{
if (gasMarkText)
for (var k in gasMarkText)
gasMarkText[k].clear();
{
if (gasMarkText[k] && gasMarkText[k].markText)
gasMarkText[k].markText.clear();
if (gasMarkText[k] && gasMarkText[k].widget)
gasMarkText[k].widget.remove();
}
}
var gasAnnotation;
@ -290,7 +309,7 @@ function listenMouseOver(e)
gasAnnotation.clear();
var cl = getGasCostClass(node);
var gasTitle = gasMarkRef[cl].value.isInfinite ? "infinite" : gasMarkRef[cl].value.gas;
gasTitle = gasTitle + " gas";
gasTitle = " execution cost: " + gasTitle + " gas";
gasAnnotation = editor.addLineWidget(gasMarkRef[cl].line + 1, makeGasCostMarker(gasTitle), { coverGutter: false, above: true });
}
else if (gasAnnotation)

72
test/libethereum/StateTestsFiller/stSpecialTestFiller.json

File diff suppressed because one or more lines are too long

140
test/libevm/VMTestsFiller/vmIOandFlowOperationsTestFiller.json

@ -854,6 +854,146 @@
}
},
"jumpToUintmaxPlus1": {
"env" : {
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6",
"currentNumber" : "0",
"currentGasLimit" : "1000000",
"currentDifficulty" : "256",
"currentTimestamp" : "1",
"currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba"
},
"expect" : {
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
"storage" : {
"0x01" : "0x00"
}
}
},
"pre" : {
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
"balance" : "100000000000000000000000",
"nonce" : "0",
"code" : "0x640100000007565b5b6001600155",
"storage": {}
}
},
"exec" : {
"address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6",
"origin" : "cd1722f3947def4cf144679da39c4c32bdc35681",
"caller" : "cd1722f3947def4cf144679da39c4c32bdc35681",
"value" : "1000000000000000000",
"data" : "",
"gasPrice" : "100000000000000",
"gas" : "100000"
}
},
"jumpToUint64maxPlus1": {
"env" : {
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6",
"currentNumber" : "0",
"currentGasLimit" : "1000000",
"currentDifficulty" : "256",
"currentTimestamp" : "1",
"currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba"
},
"expect" : {
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
"storage" : {
"0x01" : "0x00"
}
}
},
"pre" : {
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
"balance" : "100000000000000000000000",
"nonce" : "0",
"code" : "0x6801000000000000000b565b5b6001600155",
"storage": {}
}
},
"exec" : {
"address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6",
"origin" : "cd1722f3947def4cf144679da39c4c32bdc35681",
"caller" : "cd1722f3947def4cf144679da39c4c32bdc35681",
"value" : "1000000000000000000",
"data" : "",
"gasPrice" : "100000000000000",
"gas" : "100000"
}
},
"jumpiToUintmaxPlus1": {
"env" : {
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6",
"currentNumber" : "0",
"currentGasLimit" : "1000000",
"currentDifficulty" : "256",
"currentTimestamp" : "1",
"currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba"
},
"expect" : {
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
"storage" : {
"0x01" : "0x00"
}
}
},
"pre" : {
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
"balance" : "100000000000000000000000",
"nonce" : "0",
"code" : "0x6001640100000009575b5b6001600155",
"storage": {}
}
},
"exec" : {
"address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6",
"origin" : "cd1722f3947def4cf144679da39c4c32bdc35681",
"caller" : "cd1722f3947def4cf144679da39c4c32bdc35681",
"value" : "1000000000000000000",
"data" : "",
"gasPrice" : "100000000000000",
"gas" : "100000"
}
},
"jumpiToUint64maxPlus1": {
"env" : {
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6",
"currentNumber" : "0",
"currentGasLimit" : "1000000",
"currentDifficulty" : "256",
"currentTimestamp" : "1",
"currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba"
},
"expect" : {
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
"storage" : {
"0x01" : "0x00"
}
}
},
"pre" : {
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
"balance" : "100000000000000000000000",
"nonce" : "0",
"code" : "0x60016801000000000000000d575b5b6001600155",
"storage": {}
}
},
"exec" : {
"address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6",
"origin" : "cd1722f3947def4cf144679da39c4c32bdc35681",
"caller" : "cd1722f3947def4cf144679da39c4c32bdc35681",
"value" : "1000000000000000000",
"data" : "",
"gasPrice" : "100000000000000",
"gas" : "100000"
}
},
"jumpiAfterStop": {
"env" : {
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6",

100
test/libwhisper/whisperMessage.cpp

@ -0,0 +1,100 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
/** @file whisperMessage.cpp
* @author Vladislav Gluhovsky <vlad@ethdev.com>
* @date May 2015
*/
#include <boost/test/unit_test.hpp>
#include <libwhisper/Message.h>
using namespace std;
using namespace dev;
using namespace dev::shh;
struct VerbosityHolder
{
VerbosityHolder(int _temporaryValue) : oldLogVerbosity(g_logVerbosity) { g_logVerbosity = _temporaryValue; }
~VerbosityHolder() { g_logVerbosity = oldLogVerbosity; }
int oldLogVerbosity;
};
FullTopic createRandomTopics(unsigned int i)
{
FullTopic ret;
h256 t(i);
for (int j = 0; j < 8; ++j)
{
t = sha3(t);
ret.push_back(t);
}
return move(ret);
}
bytes createRandomPayload(unsigned int i)
{
bytes ret;
srand(i);
int const sz = rand() % 1024;
for (int j = 0; j < sz; ++j)
ret.push_back(rand() % 256);
return move(ret);
}
void comparePayloads(Message const& m1, Message const& m2)
{
bytes const& p1 = m1.payload();
bytes const& p2 = m2.payload();
BOOST_REQUIRE_EQUAL(p1.size(), p2.size());
for (size_t i = 0; i < p1.size(); ++i)
BOOST_REQUIRE_EQUAL(p1[i], p2[i]);
}
void sealAndOpenSingleMessage(unsigned int i)
{
Secret zero;
FullTopic topics = createRandomTopics(i);
bytes const payload = createRandomPayload(i);
Message m1(payload);
Envelope e = m1.seal(zero, topics, 1, 1);
for (auto const& t: topics)
{
FullTopic singleTopic;
singleTopic.push_back(t);
Message m2(e, singleTopic, zero);
comparePayloads(m1, m2);
}
}
BOOST_AUTO_TEST_SUITE(whisperMessage)
BOOST_AUTO_TEST_CASE(seal)
{
VerbosityHolder setTemporaryLevel(10);
cnote << "Testing Envelope encryption...";
for (unsigned int i = 1; i < 10; ++i)
sealAndOpenSingleMessage(i);
}
BOOST_AUTO_TEST_SUITE_END()
Loading…
Cancel
Save