Browse Source

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

cl-refactor
Gav Wood 10 years ago
parent
commit
e64a46c34a
  1. 3
      evmjit/libevmjit/BasicBlock.cpp
  2. 3
      evmjit/libevmjit/BasicBlock.h
  3. 8
      libdevcore/CommonIO.cpp
  4. 2
      libdevcore/CommonIO.h
  5. 16
      libdevcrypto/Common.cpp
  6. 24
      libdevcrypto/Common.h
  7. 2
      libjsconsole/JSV8Connector.cpp
  8. 17
      libjsconsole/JSV8Connector.h
  9. 29
      libjsconsole/JSV8RemoteConnector.cpp
  10. 32
      libjsconsole/JSV8RemoteConnector.h
  11. 2
      libjsengine/JSEngine.h
  12. 2
      libjsengine/JSPrinter.h
  13. 2
      libjsengine/JSV8Engine.h
  14. 2
      libjsengine/JSV8Printer.h
  15. 8
      libjsengine/JSV8RPC.cpp
  16. 8
      libjsengine/JSV8RPC.h
  17. 14
      mix/ClientModel.cpp
  18. 46
      mix/ContractCallDataEncoder.cpp
  19. 8
      mix/qml/Application.qml
  20. 34
      mix/qml/Block.qml
  21. 62
      mix/qml/BlockChain.qml
  22. 23
      mix/qml/DeployContractStep.qml
  23. 2
      mix/qml/DeploymentDialog.qml
  24. 19
      mix/qml/DeploymentWorker.qml
  25. 8
      mix/qml/RegisteringStep.qml
  26. 8
      mix/qml/ScenarioExecution.qml
  27. 51
      mix/qml/ScenarioLoader.qml
  28. 237
      mix/qml/StateDialog.qml
  29. 19
      mix/qml/StateList.qml
  30. 37
      mix/qml/StateListModel.qml
  31. 4
      mix/qml/TransactionDialog.qml
  32. 299
      test/libethereum/BlockchainTestsFiller/bcValidBlockTestFiller.json
  33. 13
      test/libethereum/blockchain.cpp
  34. 70
      test/libevm/VMTestsFiller/vmIOandFlowOperationsTestFiller.json
  35. 24
      test/libp2p/rlpx.cpp
  36. 237
      test/libsolidity/SolidityFixedFeeRegistrar.cpp
  37. 1
      test/libsolidity/solidityExecutionFramework.h
  38. 66
      test/libwhisper/whisperTopic.cpp

3
evmjit/libevmjit/BasicBlock.cpp

@ -49,7 +49,7 @@ void BasicBlock::LocalStack::push(llvm::Value* _value)
assert(_value->getType() == Type::Word);
m_bblock.m_currentStack.push_back(_value);
m_bblock.m_tosOffset += 1;
m_maxSize = std::max(m_maxSize, m_bblock.m_currentStack.size());
m_maxSize = std::max(m_maxSize, m_bblock.m_tosOffset);
}
llvm::Value* BasicBlock::LocalStack::pop()
@ -388,4 +388,3 @@ void BasicBlock::dump(std::ostream& _out, bool _dotOutput)
}
}
}

3
evmjit/libevmjit/BasicBlock.h

@ -52,7 +52,7 @@ public:
private:
BasicBlock& m_bblock;
size_t m_maxSize = 0; ///< Max size reached by the stack.
int m_maxSize = 0; ///< Max size reached by the stack.
};
explicit BasicBlock(instr_idx _firstInstrIdx, code_iterator _begin, code_iterator _end, llvm::Function* _mainFunc, llvm::IRBuilder<>& _builder, bool isJumpDest);
@ -127,4 +127,3 @@ private:
}
}
}

8
libdevcore/CommonIO.cpp

@ -91,6 +91,14 @@ bytes dev::contents(string const& _file)
return contentsGeneric<bytes>(_file);
}
bytesSec dev::contentsSec(string const& _file)
{
bytes b = contentsGeneric<bytes>(_file);
bytesSec ret(b);
bytesRef(&b).cleanse();
return ret;
}
string dev::contentsString(string const& _file)
{
return contentsGeneric<string>(_file);

2
libdevcore/CommonIO.h

@ -48,6 +48,8 @@ std::string getPassword(std::string const& _prompt);
/// Retrieve and returns the contents of the given file.
/// If the file doesn't exist or isn't readable, returns an empty container / bytes.
bytes contents(std::string const& _file);
/// Secure variation.
bytesSec contentsSec(std::string const& _file);
/// Retrieve and returns the contents of the given file as a std::string.
/// If the file doesn't exist or isn't readable, returns an empty container / bytes.
std::string contentsString(std::string const& _file);

16
libdevcrypto/Common.cpp

@ -150,7 +150,7 @@ bool dev::decryptSym(Secret const& _k, bytesConstRef _cipher, bytes& o_plain)
std::pair<bytes, h128> dev::encryptSymNoAuth(SecureFixedHash<16> const& _k, bytesConstRef _plain)
{
h128 iv(Nonce::get());
h128 iv(Nonce::get().makeInsecure());
return make_pair(encryptSymNoAuth(_k, iv, _plain), iv);
}
@ -312,7 +312,7 @@ h256 crypto::kdf(Secret const& _priv, h256 const& _hash)
mutex Nonce::s_x;
static string s_seedFile;
h256 Nonce::get()
Secret Nonce::get()
{
// todo: atomic efface bit, periodic save, kdf, rr, rng
// todo: encrypt
@ -350,11 +350,11 @@ void Nonce::initialiseIfNeeded()
if (m_value)
return;
bytes b = contents(seedFile());
bytesSec b = contentsSec(seedFile());
if (b.size() == 32)
memcpy(m_value.data(), b.data(), 32);
b.ref().populate(m_value.writable().ref());
else
m_value = h256::random();
m_value = Secret::random();
if (!m_value)
BOOST_THROW_EXCEPTION(InvalidState());
@ -363,7 +363,7 @@ void Nonce::initialiseIfNeeded()
writeFile(seedFile(), bytes());
}
h256 Nonce::next()
Secret Nonce::next()
{
initialiseIfNeeded();
m_value = sha3(m_value);
@ -374,8 +374,8 @@ void Nonce::resetInternal()
{
// this might throw
next();
writeFile(seedFile(), m_value.asBytes());
m_value = h256();
writeFile(seedFile(), m_value.ref());
m_value.clear();
}
string const& Nonce::seedFile()

24
libdevcrypto/Common.h

@ -181,7 +181,8 @@ private:
namespace crypto
{
struct InvalidState: public dev::Exception {};
DEV_SIMPLE_EXCEPTION(InvalidState);
/// Key derivation
h256 kdf(Secret const& _priv, h256 const& _hash);
@ -189,35 +190,44 @@ h256 kdf(Secret const& _priv, h256 const& _hash);
/**
* @brief Generator for nonce material.
*/
struct Nonce
class Nonce
{
public:
/// Returns the next nonce (might be read from a file).
static h256 get();
static Secret get();
/// Stores the current nonce in a file and resets Nonce to the uninitialised state.
static void reset();
/// Sets the location of the seed file to a non-default place. Used for testing.
static void setSeedFilePath(std::string const& _filePath);
private:
Nonce() {}
Nonce() = default;
~Nonce();
/// @returns the singleton instance.
static Nonce& singleton();
/// Reads the last seed from the seed file.
void initialiseIfNeeded();
/// @returns the next nonce.
h256 next();
Secret next();
/// Stores the current seed in the seed file.
void resetInternal();
/// @returns the path of the seed file.
static std::string const& seedFile();
Secret m_value;
/// Mutex for the singleton object.
/// @note Every access to any private function has to be guarded by this mutex.
static std::mutex s_x;
h256 m_value;
};
}
}

2
libjsconsole/JSV8Connector.cpp

@ -39,7 +39,7 @@ bool JSV8Connector::StopListening()
bool JSV8Connector::SendResponse(std::string const& _response, void* _addInfo)
{
(void)_addInfo;
m_lastResponse = _response.c_str();
m_lastResponse = _response;
return true;
}

17
libjsconsole/JSV8Connector.h

@ -22,6 +22,7 @@
#pragma once
#include <string>
#include <jsonrpccpp/server/abstractserverconnector.h>
#include <libjsengine/JSV8RPC.h>
@ -30,20 +31,24 @@ namespace dev
namespace eth
{
class JSV8Connector: public jsonrpc::AbstractServerConnector, public JSV8RPC
class JSV8Connector: public jsonrpc::AbstractServerConnector, private JSV8RPC
{
public:
JSV8Connector(JSV8Engine const& _engine): JSV8RPC(_engine) {}
virtual ~JSV8Connector();
// implement AbstractServerConnector interface
bool StartListening();
bool StopListening();
bool SendResponse(std::string const& _response, void* _addInfo = nullptr);
bool StartListening() override;
bool StopListening() override;
bool SendResponse(std::string const& _response, void* _addInfo = nullptr) override;
private:
// implement JSV8RPC interface
void onSend(char const* _payload);
void onSend(char const* _payload) override;
char const* lastResponse() const override { return m_lastResponse.c_str(); }
std::string m_lastResponse = R"({"id": 1, "jsonrpc": "2.0", "error": "Uninitalized JSV8RPC!"})";
};
}

29
libjsconsole/JSV8RemoteConnector.cpp

@ -1,10 +1,27 @@
//
// Created by Marek Kotewicz on 15/06/15.
//
/*
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 JSV8RemoteConnector.cpp
* @author Marek Kotewicz <marek@ethdev.com>
* @date 2015
* Connector from the standalone javascript console to a remote RPC node.
*/
#include "JSV8RemoteConnector.h"
using namespace std;
using namespace dev;
using namespace dev::eth;
@ -13,8 +30,6 @@ void JSV8RemoteConnector::onSend(char const* _payload)
m_request.setUrl(m_url);
m_request.setBody(_payload);
long code;
string response;
tie(code, response) = m_request.post();
tie(code, m_lastResponse) = m_request.post();
(void)code;
m_lastResponse = response.c_str();
}

32
libjsconsole/JSV8RemoteConnector.h

@ -1,10 +1,27 @@
//
// Created by Marek Kotewicz on 15/06/15.
//
/*
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 JSV8RemoteConnector.cpp
* @author Marek Kotewicz <marek@ethdev.com>
* @date 2015
* Connector from the standalone javascript console to a remote RPC node.
*/
#pragma once
#include <string>
#include <libjsengine/JSV8RPC.h>
#include "CURLRequest.h"
@ -13,18 +30,21 @@ namespace dev
namespace eth
{
class JSV8RemoteConnector : public JSV8RPC
class JSV8RemoteConnector: private JSV8RPC
{
public:
JSV8RemoteConnector(JSV8Engine const& _engine, std::string _url): JSV8RPC(_engine), m_url(_url) {}
virtual ~JSV8RemoteConnector() {}
private:
// implement JSV8RPC interface
void onSend(char const* _payload);
void onSend(char const* _payload) override;
const char* lastResponse() const override { return m_lastResponse.c_str(); }
private:
std::string m_url;
std::string m_lastResponse = R"({"id": 1, "jsonrpc": "2.0", "error": "Uninitalized JSV8RPC!"})";
CURLRequest m_request;
};

2
libjsengine/JSEngine.h

@ -23,6 +23,8 @@
#pragma once
#include <exception>
/// Do not use libstd headers here, it will break on MacOS.
namespace dev
{
namespace eth

2
libjsengine/JSPrinter.h

@ -24,6 +24,8 @@
#include "JSEngine.h"
/// Do not use libstd headers here, it will break on MacOS.
namespace dev
{
namespace eth

2
libjsengine/JSV8Engine.h

@ -28,6 +28,8 @@
#pragma clang diagnostic pop
#include "JSEngine.h"
/// Do not use libstd headers here, it will break on MacOS.
namespace dev
{
namespace eth

2
libjsengine/JSV8Printer.h

@ -25,6 +25,8 @@
#include "JSPrinter.h"
#include "JSV8Engine.h"
/// Do not use libstd headers here, it will break on MacOS.
namespace dev
{
namespace eth

8
libjsengine/JSV8RPC.cpp

@ -89,12 +89,4 @@ JSV8RPC::JSV8RPC(JSV8Engine const& _engine): m_engine(_engine)
v8::Handle<v8::Function> func = v8::Handle<v8::Function>::Cast(web3object->Get(setProvider));
v8::Local<v8::Value> values[1] = {obj};
func->Call(func, 1, values);
m_lastResponse = R"(
{
"id": 1,
"jsonrpc": "2.0",
"error": "Uninitalized JSV8RPC!"
}
)";
}

8
libjsengine/JSV8RPC.h

@ -24,6 +24,8 @@
#include <libjsengine/JSV8Engine.h>
/// Do not use libstd headers here, it will break on MacOS.
namespace dev
{
namespace eth
@ -33,14 +35,12 @@ class JSV8RPC
{
public:
JSV8RPC(JSV8Engine const& _engine);
virtual ~JSV8RPC() { }
virtual void onSend(char const* _payload) = 0;
char const* lastResponse() const { return m_lastResponse; }
virtual char const* lastResponse() const = 0;
private:
JSV8Engine const& m_engine;
protected:
char const* m_lastResponse;
};
}

14
mix/ClientModel.cpp

@ -236,6 +236,7 @@ void ClientModel::setupScenario(QVariantMap _scenario)
QVariantList blocks = _scenario.value("blocks").toList();
QVariantList stateAccounts = _scenario.value("accounts").toList();
QVariantList stateContracts = _scenario.value("contracts").toList();
m_accounts.clear();
m_accountsSecret.clear();
@ -258,6 +259,19 @@ void ClientModel::setupScenario(QVariantMap _scenario)
}
m_ethAccounts->setAccounts(m_accountsSecret);
for (auto const& c: stateContracts)
{
QVariantMap contract = c.toMap();
Address address = Address(fromHex(contract.value("address").toString().toStdString()));
Account account(qvariant_cast<QEther*>(contract.value("balance"))->toU256Wei(), Account::ContractConception);
bytes code = fromHex(contract.value("code").toString().toStdString());
account.setCode(std::move(code));
QVariantMap storageMap = contract.value("storage").toMap();
for(auto s = storageMap.cbegin(); s != storageMap.cend(); ++s)
account.setStorage(fromBigEndian<u256>(fromHex(s.key().toStdString())), fromBigEndian<u256>(fromHex(s.value().toString().toStdString())));
m_accounts[address] = account;
}
bool trToExecute = false;
for (auto const& b: blocks)
{

46
mix/ContractCallDataEncoder.cpp

@ -21,6 +21,7 @@
*/
#include <vector>
#include <QtCore/qmath.h>
#include <QMap>
#include <QStringList>
#include <QJsonArray>
@ -101,9 +102,9 @@ void ContractCallDataEncoder::encode(QVariant const& _data, SolidityType const&
bytes empty(32);
size_t sizePos = m_dynamicData.size();
m_dynamicData += empty; //reserve space for count
u256 count = encodeSingleItem(_data.toString(), _type, m_dynamicData);
encodeSingleItem(_data.toString(), _type, m_dynamicData);
vector_ref<byte> sizeRef(m_dynamicData.data() + sizePos, 32);
toBigEndian(count, sizeRef);
toBigEndian(_data.toString().size(), sizeRef);
m_staticOffsetMap.push_back(std::make_pair(m_encodedData.size(), sizePos));
m_encodedData += empty; //reserve space for offset
}
@ -223,10 +224,6 @@ dev::bytes ContractCallDataEncoder::decodeBytes(dev::bytes const& _rawValue)
QString ContractCallDataEncoder::toString(dev::bytes const& _b)
{
QString str;
if (asString(_b, str))
return "\"" + str + "\" " + QString::fromStdString(dev::toJS(_b));
else
return QString::fromStdString(dev::toJS(_b));
}
@ -242,8 +239,6 @@ QJsonValue ContractCallDataEncoder::decodeArrayContent(SolidityType const& _type
if (_type.baseType->array)
{
QJsonArray sub = decodeArray(*_type.baseType, _value, pos);
if (_type.baseType->dynamicSize)
pos = pos + 32;
return sub;
}
else
@ -262,6 +257,8 @@ QJsonArray ContractCallDataEncoder::decodeArray(SolidityType const& _type, bytes
QJsonArray array;
bytesConstRef value(&_value);
int count = 0;
bigint offset = pos;
int valuePosition = pos;
if (!_type.dynamicSize)
count = _type.count;
else
@ -269,14 +266,33 @@ QJsonArray ContractCallDataEncoder::decodeArray(SolidityType const& _type, bytes
bytesConstRef value(_value.data() + pos, 32); // offset
bytes rawParam(32);
value.populate(&rawParam);
bigint offset = decodeInt(rawParam);
pos = static_cast<int>(offset) + 32;
value = bytesConstRef(_value.data() + static_cast<int>(offset), 32); // offset
offset = decodeInt(rawParam);
valuePosition = static_cast<int>(offset) + 32;
pos += 32;
value = bytesConstRef(_value.data() + static_cast<int>(offset), 32); // count
value.populate(&rawParam);
count = static_cast<int>(decodeInt(rawParam));
}
if (_type.type == QSolidityType::Type::Bytes || _type.type == QSolidityType::Type::String)
{
bytesConstRef value(_value.data() + (static_cast<int>(offset) + 32), 32);
bytes rawParam(count);
value.populate(&rawParam);
if (_type.type == QSolidityType::Type::Bytes)
array.append(toString(decodeBytes(rawParam)));
else
array.append(toChar(decodeBytes(rawParam)));
}
else
{
for (int k = 0; k < count; ++k)
{
if (_type.dynamicSize)
array.append(decodeArrayContent(_type, _value, valuePosition));
else
array.append(decodeArrayContent(_type, _value, pos));
}
}
return array;
}
@ -329,18 +345,14 @@ QStringList ContractCallDataEncoder::decode(QList<QVariableDeclaration*> const&
QJsonArray array = decodeArray(type, _v, readPosition);
QJsonDocument jsonDoc = QJsonDocument::fromVariant(array.toVariantList());
r.append(jsonDoc.toJson(QJsonDocument::Compact));
if (type.dynamicSize)
readPosition++;
else
readPosition = type.count;
}
else
{
bytesConstRef value(_value.data() + (readPosition * 32), 32);
bytesConstRef value(_value.data() + readPosition, 32);
bytes rawParam(32);
value.populate(&rawParam);
r.append(decode(type, rawParam).toString());
readPosition++;
readPosition += 32;
}
}
return r;

8
mix/qml/Application.qml

@ -108,12 +108,14 @@ ApplicationWindow {
title: qsTr("Deploy")
MenuItem { action: mineAction }
MenuSeparator {}
MenuItem { action: editStatesAction }
MenuSeparator {}
MenuItem { action: deployViaRpcAction }
MenuSeparator {}
MenuItem { action: toggleRunOnLoadAction }
}
Menu {
title: qsTr("Scenario")
MenuItem { action: editStatesAction }
}
Menu {
title: qsTr("Debug")
MenuItem { action: debugRunAction }
@ -184,7 +186,7 @@ ApplicationWindow {
Action {
id: editStatesAction
text: qsTr("Edit States")
text: qsTr("Edit Scenarii")
shortcut: "Ctrl+Alt+E"
onTriggered: stateList.open();
}

34
mix/qml/Block.qml

@ -22,6 +22,7 @@ ColumnLayout
property int blockIndex
property variant scenario
property string labelColor: "#414141"
property int scenarioIndex
signal txSelected(var txIndex)
function calculateHeight()
@ -45,6 +46,11 @@ ColumnLayout
transactionDialog.open(txIndex, blockIndex, transactions.get(txIndex))
}
function select(txIndex)
{
transactionRepeater.itemAt(txIndex).select()
}
onOpenedTrChanged:
{
Layout.preferredHeight = calculateHeight()
@ -90,7 +96,7 @@ ColumnLayout
text:
{
if (number === -2)
return qsTr("STARTING PARAMETERS")
return qsTr("GENESIS PARAMETERS")
else if (status === "mined")
return qsTr("BLOCK") + " " + number
else
@ -105,13 +111,14 @@ ColumnLayout
anchors.verticalCenter: parent.verticalCenter
anchors.right: parent.right
anchors.rightMargin: 14
visible: false
visible: number === -2
MouseArea
{
anchors.fill: parent
onClicked:
{
// load edit block panel
projectModel.stateListModel.editState(scenarioIndex)
}
}
}
@ -127,6 +134,12 @@ ColumnLayout
id: rowTransaction
Layout.preferredHeight: trHeight
spacing: 0
function select()
{
rowContentTr.select()
}
function displayContent()
{
logsText.text = ""
@ -220,6 +233,15 @@ ColumnLayout
}
}
function select()
{
rowContentTr.selected = true
rowContentTr.color = "#4F4F4F"
hash.color = "#EAB920"
func.color = "#EAB920"
txSelected(index)
}
function deselect()
{
rowContentTr.selected = false
@ -233,13 +255,7 @@ ColumnLayout
anchors.fill: parent
onClicked: {
if (!rowContentTr.selected)
{
rowContentTr.selected = true
rowContentTr.color = "#4F4F4F"
hash.color = "#EAB920"
func.color = "#EAB920"
txSelected(index)
}
rowContentTr.select()
else
rowContentTr.deselect()

62
mix/qml/BlockChain.qml

@ -16,6 +16,7 @@ ColumnLayout {
property alias trDialog: transactionDialog
property alias blockChainRepeater: blockChainRepeater
property variant model
property int scenarioIndex
property var states: ({})
spacing: 0
property int previousWidth
@ -26,6 +27,25 @@ ColumnLayout {
signal rebuilding
signal accountAdded(string address, string amount)
Connections
{
target: projectModel.stateListModel
onAccountsValidated:
{
if (rebuild.accountsSha3 !== codeModel.sha3(JSON.stringify(_accounts)))
rebuild.needRebuild("AccountsChanged")
else
rebuild.notNeedRebuild("AccountsChanged")
}
onContractsValidated:
{
if (rebuild.contractsSha3 !== codeModel.sha3(JSON.stringify(_contracts)))
rebuild.needRebuild("ContractsChanged")
else
rebuild.notNeedRebuild("ContractsChanged")
}
}
Connections
{
target: codeModel
@ -94,13 +114,15 @@ ColumnLayout {
return states[record]
}
function load(scenario)
function load(scenario, index)
{
if (!scenario)
return;
if (model)
rebuild.startBlinking()
model = scenario
scenarioIndex = index
genesis.scenarioIndex = index
states = []
blockModel.clear()
for (var b in model.blocks)
@ -138,6 +160,20 @@ ColumnLayout {
width: parent.width
spacing: 20
Block
{
id: genesis
scenario: blockChainPanel.model
scenarioIndex: scenarioIndex
Layout.preferredWidth: blockChainScrollView.width
Layout.preferredHeight: 60
blockIndex: -1
transactions: []
status: ""
number: -2
trHeight: 60
}
Repeater // List of blocks
{
id: blockChainRepeater
@ -148,6 +184,11 @@ ColumnLayout {
itemAt(blockIndex).editTx(txIndex)
}
function select(blockIndex, txIndex)
{
itemAt(blockIndex).select(txIndex)
}
Block
{
Connections
@ -264,6 +305,8 @@ ColumnLayout {
roundRight: true
property variant contractsHex: ({})
property variant txSha3: ({})
property variant accountsSha3
property variant contractsSha3
property variant txChanged: []
property var blinkReasons: []
@ -352,10 +395,22 @@ ColumnLayout {
ensureNotFuturetime.start()
takeCodeSnapshot()
takeTxSnaphot()
takeAccountsSnapshot()
takeContractsSnapShot()
blinkReasons = []
clientModel.setupScenario(model);
}
function takeContractsSnapShot()
{
contractsSha3 = codeModel.sha3(JSON.stringify(model.contracts))
}
function takeAccountsSnapshot()
{
accountsSha3 = codeModel.sha3(JSON.stringify(model.accounts))
}
function takeCodeSnapshot()
{
contractsHex = {}
@ -394,6 +449,8 @@ ColumnLayout {
id: addTransaction
text: qsTr("Add Tx")
onClicked:
{
if (model && model.blocks)
{
var lastBlock = model.blocks[model.blocks.length - 1];
if (lastBlock.status === "mined")
@ -409,6 +466,7 @@ ColumnLayout {
transactionDialog.editMode = false
transactionDialog.open(model.blocks[model.blocks.length - 1].transactions.length, model.blocks.length - 1, item)
}
}
width: 100
height: 30
buttonShortcut: ""
@ -516,6 +574,7 @@ ColumnLayout {
trModel.sender = _r.sender
trModel.returnParameters = _r.returnParameters
blockModel.setTransaction(blockIndex, trIndex, trModel)
blockChainRepeater.select(blockIndex, trIndex)
return;
}
}
@ -537,6 +596,7 @@ ColumnLayout {
itemTr.returnParameters = _r.returnParameters
model.blocks[model.blocks.length - 1].transactions.push(itemTr)
blockModel.appendTransaction(itemTr)
blockChainRepeater.select(blockIndex, trIndex)
}
onNewState: {

23
mix/qml/DeployContractStep.qml

@ -36,6 +36,19 @@ Rectangle {
accountsList.currentIndex = 0
}
verifyDeployedContract()
deployedAddresses.refresh()
worker.renewCtx()
worker.pooler.onTriggered.connect(function() {
if (root.visible)
verifyDeployedContract();
})
}
function verifyDeployedContract()
{
if (projectModel.deployBlockNumber !== -1)
{
worker.verifyHashes(projectModel.deploymentTrHashes, function (bn, trLost)
@ -43,8 +56,6 @@ Rectangle {
root.updateVerification(bn, trLost)
});
}
deployedAddresses.refresh()
worker.renewCtx()
}
function updateVerification(blockNumber, trLost)
@ -112,14 +123,10 @@ Rectangle {
for (var k = 0; k < projectModel.stateListModel.get(currentIndex).blocks.count; k++)
{
for (var j = 0; j < projectModel.stateListModel.get(currentIndex).blocks.get(k).transactions.count; j++)
{
trListModel.append(projectModel.stateListModel.get(currentIndex).blocks.get(k).transactions.get(j));
}
}
for (var k = 0; k < trListModel.count; k++)
{
trList.itemAt(k).init()
}
ctrDeployCtrLabel.calculateContractDeployGas();
}
}
@ -166,11 +173,9 @@ Rectangle {
if (trListModel.get(index).parameters)
{
for (var k in trListModel.get(index).parameters)
{
paramList.append({ "name": k, "value": trListModel.get(index).parameters[k] })
}
}
}
Label
{
@ -220,7 +225,6 @@ Rectangle {
}
}
ColumnLayout
{
anchors.top: parent.top
@ -486,6 +490,7 @@ Rectangle {
id: clearDeployAction
onTriggered: {
worker.forceStopPooling()
if (projectModel.deploymentDir && projectModel.deploymentDir !== "")
fileIo.deleteDir(projectModel.deploymentDir)
projectModel.cleanDeploymentStatus()
deploymentDialog.steps.reset()

2
mix/qml/DeploymentDialog.qml

@ -27,6 +27,7 @@ Dialog {
function close()
{
visible = false;
worker.pooler.running = false
}
function open()
@ -36,6 +37,7 @@ Dialog {
registerStep.visible = false
steps.init()
worker.renewCtx()
worker.pooler.running = true
visible = true;
}

19
mix/qml/DeploymentWorker.qml

@ -19,6 +19,7 @@ Item
property alias gasPriceInt: gasPriceInt
property variant balances: ({})
property variant accounts: []
property alias pooler: pooler
signal gasPriceLoaded()
function renewCtx()
@ -169,10 +170,11 @@ Item
{
if (!clientModelGasEstimation.running)
{
var ctr = projectModel.codeEditor.getContracts()
for (var k in ctr)
for (var si = 0; si < projectModel.listModel.count; si++)
{
codeModelGasEstimation.registerCodeChange(ctr[k].document.documentId, ctr[k].getText());
var document = projectModel.listModel.get(si);
if (document.isContract)
codeModelGasEstimation.registerCodeChange(document.documentId, fileIo.readFile(document.path));
}
gasEstimationConnect.callback = callback
clientModelGasEstimation.setupScenario(scenario)
@ -193,7 +195,8 @@ Item
id: codeModelGasEstimation
}
ClientModel {
ClientModel
{
id: clientModelGasEstimation
codeModel: codeModelGasEstimation
Component.onCompleted:
@ -202,6 +205,14 @@ Item
}
}
Timer
{
id: pooler
interval: 5000
repeat: true
running: false
}
Timer
{
id: poolLog

8
mix/qml/RegisteringStep.qml

@ -32,6 +32,14 @@ Rectangle {
visible = true
worker.pooler.onTriggered.connect(function() {
if (root.visible)
verifyRegistering();
})
}
function verifyRegistering()
{
verificationEthUrl.text = ""
if (projectModel.registerContentHashTrHash !== "" && projectModel.registerContentHashBlockNumber !== -1)
{

8
mix/qml/ScenarioExecution.qml

@ -70,7 +70,7 @@ Rectangle {
onLoaded:
{
watchers.clear()
blockChain.load(scenario)
blockChain.load(scenario, loader.selectedScenarioIndex)
}
}
@ -85,13 +85,15 @@ Rectangle {
target: blockChain
property var currentSelectedBlock
property var currentSelectedTx
onTxSelected: {
onTxSelected:
{
currentSelectedBlock = blockIndex
currentSelectedTx = txIndex
updateWatchers(blockIndex, txIndex)
}
function updateWatchers(blockIndex, txIndex){
function updateWatchers(blockIndex, txIndex)
{
var tx = blockChain.model.blocks[blockIndex].transactions[txIndex]
var state = blockChain.getState(tx.recordIndex)
watchers.updateWidthTx(tx, state, blockIndex, txIndex)

51
mix/qml/ScenarioLoader.qml

@ -20,6 +20,7 @@ ColumnLayout
signal loaded(variant scenario)
signal renamed(variant scenario)
signal deleted()
property alias selectedScenarioIndex: scenarioList.currentIndex
spacing: 0
function init()
{
@ -80,15 +81,14 @@ ColumnLayout
}
}
Label
{
anchors.left: editImg.right
text: "X"
height: parent.height
color: "#cccccc"
Image {
source: "qrc:/qml/img/delete_sign.png"
height: parent.height - 16
fillMode: Image.PreserveAspectFit
id: deleteImg
anchors.left: editImg.right
anchors.top: parent.top
anchors.topMargin: 7
anchors.topMargin: 8
visible: projectModel.stateListModel.count > 1
MouseArea
{
@ -98,10 +98,34 @@ ColumnLayout
if (projectModel.stateListModel.count > 1)
{
projectModel.stateListModel.deleteState(scenarioList.currentIndex)
scenarioList.currentIndex = 0
deleted()
scenarioList.init()
}
}
}
}
Label
{
MouseArea
{
anchors.fill: parent
onClicked:
{
if (projectModel.stateListModel.count > 1)
{
projectModel.stateListModel.deleteState(scenarioList.currentIndex)
scenarioList.init()
}
}
}
}
Connections
{
target: projectModel.stateListModel
onStateDeleted: {
scenarioList.init()
}
}
@ -122,6 +146,12 @@ ColumnLayout
restoreScenario.restore()
}
function init()
{
scenarioList.currentIndex = 0
deleted()
}
function load()
{
var state = projectModel.stateListModel.getState(currentIndex)
@ -291,7 +321,7 @@ ColumnLayout
text: qsTr("Restore")
function restore()
{
var state = projectModel.stateListModel.reloadStateFromFromProject(scenarioList.currentIndex)
var state = projectModel.stateListModel.reloadStateFromProject(scenarioList.currentIndex)
if (state)
{
restored(state)
@ -302,7 +332,6 @@ ColumnLayout
roundLeft: true
}
Rectangle
{
width: 1

237
mix/qml/StateDialog.qml

@ -18,12 +18,8 @@ Dialog {
title: qsTr("Edit State")
visible: false
property alias stateTitle: titleField.text
property alias isDefault: defaultCheckBox.checked
property alias model: transactionsModel
property alias transactionDialog: transactionDialog
property alias minerComboBox: comboMiner
property alias newAccAction: newAccountAction
property int stateIndex
property var stateTransactions: []
property var stateAccounts: []
@ -36,16 +32,6 @@ Dialog {
function open(index, item, setDefault) {
stateIndex = index
stateTitle = item.title
transactionsModel.clear()
stateTransactions = []
var transactions = item.transactions
for (var t = 0; t < transactions.length; t++) {
transactionsModel.append(item.transactions[t])
stateTransactions.push(item.transactions[t])
}
accountsModel.clear()
stateAccounts = []
var miner = 0
@ -66,8 +52,8 @@ Dialog {
visible = true
isDefault = setDefault
titleField.focus = true
defaultCheckBox.enabled = !isDefault
console.log(isDefault)
defaultCheckBox.checked = isDefault
comboMiner.model = stateAccounts
comboMiner.currentIndex = miner
forceActiveFocus()
@ -84,8 +70,6 @@ Dialog {
function getItem() {
var item = {
title: stateDialog.stateTitle,
transactions: stateTransactions,
accounts: stateAccounts,
contracts: stateContracts
}
@ -95,6 +79,7 @@ Dialog {
break
}
}
item.defaultState = defaultCheckBox.checked
return item
}
@ -111,21 +96,6 @@ Dialog {
ColumnLayout {
id: dialogContent
anchors.top: parent.top
RowLayout {
Layout.fillWidth: true
DefaultLabel {
Layout.preferredWidth: 85
text: qsTr("Title")
}
DefaultTextField {
id: titleField
Layout.fillWidth: true
}
}
CommonSeparator {
Layout.fillWidth: true
}
RowLayout {
Layout.fillWidth: true
@ -258,30 +228,6 @@ Dialog {
Layout.preferredWidth: 85
text: qsTr("Accounts")
}
Button {
id: newAccountButton
anchors.top: accountsLabel.bottom
anchors.topMargin: 10
iconSource: "qrc:/qml/img/plus.png"
action: newAccountAction
}
Action {
id: newAccountAction
tooltip: qsTr("Add new Account")
onTriggered: {
add()
}
function add() {
var account = stateListModel.newAccount(
"1000000", QEther.Ether)
stateAccounts.push(account)
accountsModel.append(account)
return account
}
}
}
MessageDialog {
@ -313,21 +259,8 @@ Dialog {
id: deleteAccountAction
tooltip: qsTr("Delete Account")
onTriggered: {
if (transactionsModel.isUsed(
stateAccounts[styleData.row].secret))
alertAlreadyUsed.open()
else {
if (stateAccounts[styleData.row].name
=== comboMiner.currentText)
comboMiner.currentIndex = 0
stateAccounts.splice(
styleData.row,
1)
accountsModel.remove(
styleData.row)
comboMiner.model = stateAccounts //TODO: filter accounts wo private keys
comboMiner.update()
}
stateAccounts.splice(styleData.row, 1)
accountsView.model.remove(styleData.row)
}
}
@ -405,138 +338,25 @@ Dialog {
Layout.fillWidth: true
}
RowLayout {
Layout.fillWidth: true
Rectangle {
Layout.preferredWidth: 85
DefaultLabel {
id: transactionsLabel
Layout.preferredWidth: 85
text: qsTr("Transactions")
}
Button {
anchors.top: transactionsLabel.bottom
anchors.topMargin: 10
iconSource: "qrc:/qml/img/plus.png"
action: newTrAction
}
Action {
id: newTrAction
tooltip: qsTr("Create a new transaction")
onTriggered: transactionsModel.addTransaction()
}
}
TableView {
id: transactionsView
Layout.fillWidth: true
model: transactionsModel
headerVisible: false
TableViewColumn {
role: "label"
title: qsTr("Name")
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: {
if (styleData.row >= 0)
return transactionsModel.get(
styleData.row).label
else
return ""
}
}
}
}
}
rowDelegate: Rectangle {
color: styleData.alternate ? "transparent" : "#f0f0f0"
height: 30
}
}
}
}
RowLayout {
anchors.bottom: parent.bottom
anchors.right: parent.right
Button {
text: qsTr("Delete")
enabled: !modalStateDialog.isDefault
onClicked: {
projectModel.stateListModel.deleteState(stateIndex)
close()
}
}
Button {
text: qsTr("OK")
onClicked: {
if (titleField.text === "")
alertDialog.open()
else
{
close()
accepted()
}
}
}
Button {
text: qsTr("Cancel")
onClicked: close()
}
}
MessageDialog
{
id: alertDialog
text: qsTr("Please provide a name.")
}
ListModel {
id: accountsModel
function removeAccount(_i) {
accountsModel.remove(_i)
stateAccounts.splice(_i, 1)
}
}
ListModel {
id: contractsModel
@ -547,50 +367,11 @@ Dialog {
}
ListModel {
id: transactionsModel
function editTransaction(index) {
transactionDialog.stateAccounts = stateAccounts
transactionDialog.open(index,
transactionsModel.get(index))
}
function addTransaction() {
// Set next id here to work around Qt bug
// 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
var item = TransactionHelper.defaultTransaction()
transactionDialog.stateAccounts = stateAccounts
transactionDialog.open(transactionsModel.count, item)
}
function deleteTransaction(index) {
stateTransactions.splice(index, 1)
transactionsModel.remove(index)
}
function isUsed(secret) {
for (var i in stateTransactions) {
if (stateTransactions[i].sender === secret)
return true
}
return false
}
}
id: accountsModel
TransactionDialog {
id: transactionDialog
onAccepted: {
var item = transactionDialog.getItem()
if (transactionDialog.transactionIndex < transactionsModel.count) {
transactionsModel.set(
transactionDialog.transactionIndex,
item)
stateTransactions[transactionDialog.transactionIndex] = item
} else {
transactionsModel.append(item)
stateTransactions.push(item)
}
function removeAccount(_i) {
accountsModel.remove(_i)
stateAccounts.splice(_i, 1)
}
}
}

19
mix/qml/StateList.qml

@ -27,7 +27,7 @@ Dialog {
frameVisible: false
TableViewColumn {
role: "title"
title: qsTr("State")
title: qsTr("Scenario")
width: list.width
}
}
@ -37,10 +37,6 @@ Dialog {
anchors.bottom: parent.bottom
anchors.right: parent.right
anchors.rightMargin: 10
Button {
action: addStateAction
}
Button {
action: closeAction
}
@ -71,25 +67,12 @@ Dialog {
Layout.fillHeight: true
onClicked: list.model.deleteState(styleData.row);
}
ToolButton {
text: qsTr("Run");
Layout.fillHeight: true
onClicked: list.model.runState(styleData.row);
}
}
}
}
Row
{
Action {
id: addStateAction
text: qsTr("Add State")
shortcut: "Ctrl+T"
enabled: codeModel.hasContract && !clientModel.running;
onTriggered: list.model.addState();
}
Action {
id: closeAction
text: qsTr("Close")

37
mix/qml/StateListModel.qml

@ -186,12 +186,13 @@ Item {
onProjectLoading: stateListModel.loadStatesFromProject(projectData);
onProjectFileSaving: {
projectData.states = []
for(var i = 0; i < stateListModel.count; i++) {
for(var i = 0; i < stateListModel.count; i++)
{
projectData.states.push(toPlainStateItem(stateList[i]));
stateListModel.set(i, stateList[i]);
}
projectData.defaultStateIndex = stateListModel.defaultStateIndex;
stateListModel.data = projectData
}
onNewProject: {
var state = toPlainStateItem(stateListModel.createDefaultState());
@ -221,20 +222,19 @@ Item {
function saveState(item)
{
if (stateDialog.stateIndex < stateListModel.count) {
if (stateDialog.isDefault)
stateListModel.defaultStateIndex = stateIndex;
stateList[stateDialog.stateIndex] = item;
stateListModel.set(stateDialog.stateIndex, item);
} else {
if (stateDialog.isDefault)
stateListModel.defaultStateIndex = 0;
stateList.push(item);
stateListModel.append(item);
stateList[stateDialog.stateIndex].accounts = item.accounts
stateList[stateDialog.stateIndex].contracts = item.contracts
stateListModel.get(stateDialog.stateIndex).accounts = item.accounts
stateListModel.get(stateDialog.stateIndex).contracts = item.contracts
stateListModel.accountsValidated(item.accounts)
stateListModel.contractsValidated(item.contracts)
stateListModel.get(stateDialog.stateIndex).miner = item.miner
stateList[stateDialog.stateIndex].miner = item.miner
if (item.defaultState)
{
stateListModel.defaultStateIndex = stateDialog.stateIndex
stateListModel.defaultStateChanged()
}
if (stateDialog.isDefault)
stateListModel.defaultStateChanged();
stateListModel.save();
}
}
@ -242,12 +242,15 @@ Item {
id: stateListModel
property int defaultStateIndex: 0
property variant data
signal accountsValidated(var _accounts)
signal contractsValidated(var _contracts)
signal defaultStateChanged;
signal stateListModelReady;
signal stateRun(int index)
signal stateDeleted(int index)
function defaultTransactionItem() {
function defaultTransactionItem()
{
return TransactionHelper.defaultTransaction();
}
@ -409,7 +412,7 @@ Item {
return ""
}
function reloadStateFromFromProject(index)
function reloadStateFromProject(index)
{
if (data)
{

4
mix/qml/TransactionDialog.qml

@ -125,7 +125,7 @@ Dialog {
function loadParameters() {
paramsModel = []
if (functionComboBox.currentIndex >= 0 && functionComboBox.currentIndex < functionsModel.count) {
var contract = codeModel.contracts[TransactionHelper.contractFromToken(contractCreationComboBox.currentValue())];
var contract = codeModel.contracts[TransactionHelper.contractFromToken(recipientsAccount.currentValue())];
if (contract) {
var func = getFunction(functionComboBox.currentText, contract);
if (func) {
@ -498,11 +498,9 @@ Dialog {
paramScroll.visible = paramsModel.length > 0
paramScroll.Layout.preferredHeight = paramsModel.length < 6 ? paramsModel.length * 30 : 205
if (paramsModel.length === 0)
{
paramScroll.height = 0
}
}
}
RowLayout
{

299
test/libethereum/BlockchainTestsFiller/bcValidBlockTestFiller.json

@ -1,4 +1,300 @@
{
"timeDiff12" : {
"genesisBlockHeader" : {
"bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"coinbase" : "0x8888f1f195afa192cfee860698584c030f4c9db1",
"difficulty" : "231072",
"extraData" : "0x42",
"gasLimit" : "3141592",
"gasUsed" : "0",
"mixHash" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"nonce" : "0x0102030405060708",
"number" : "0",
"parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
"receiptTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"stateRoot" : "0xf99eb1626cfa6db435c0836235942d7ccaa935f1ae247d3f1c21e495685f903a",
"timestamp" : "0x54c98c81",
"transactionsTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"uncleHash" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
},
"expect" : {
"095e7baea6a6c7c4c2dfeb977efac326af552d87" : {
"balance" : "100"
}
},
"pre" : {
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
"balance" : "100000000000",
"nonce" : "0",
"code" : "",
"storage": {}
},
"095e7baea6a6c7c4c2dfeb977efac326af552d87" : {
"balance" : "100",
"nonce" : "0",
"code" : "{ (MSTORE 0 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) (LOG1 0 32 0) }",
"storage": {}
}
},
"blocks" : [
{
"transactions" : [
{
"data" : "",
"gasLimit" : "50000",
"gasPrice" : "10",
"nonce" : "0",
"secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
"to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87",
"value" : "5000"
}
],
"uncleHeaders" : [
]
},
{
"blockHeader" : {
"RelTimestamp" : "12"
},
"transactions" : [
{
"data" : "",
"gasLimit" : "50000",
"gasPrice" : "10",
"nonce" : "0",
"secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
"to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87",
"value" : "5000"
}
],
"uncleHeaders" : [
]
}
]
},
"timeDiff13" : {
"genesisBlockHeader" : {
"bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"coinbase" : "0x8888f1f195afa192cfee860698584c030f4c9db1",
"difficulty" : "231072",
"extraData" : "0x42",
"gasLimit" : "3141592",
"gasUsed" : "0",
"mixHash" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"nonce" : "0x0102030405060708",
"number" : "0",
"parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
"receiptTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"stateRoot" : "0xf99eb1626cfa6db435c0836235942d7ccaa935f1ae247d3f1c21e495685f903a",
"timestamp" : "0x54c98c81",
"transactionsTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"uncleHash" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
},
"expect" : {
"095e7baea6a6c7c4c2dfeb977efac326af552d87" : {
"balance" : "100"
}
},
"pre" : {
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
"balance" : "100000000000",
"nonce" : "0",
"code" : "",
"storage": {}
},
"095e7baea6a6c7c4c2dfeb977efac326af552d87" : {
"balance" : "100",
"nonce" : "0",
"code" : "{ (MSTORE 0 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) (LOG1 0 32 0) }",
"storage": {}
}
},
"blocks" : [
{
"transactions" : [
{
"data" : "",
"gasLimit" : "50000",
"gasPrice" : "10",
"nonce" : "0",
"secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
"to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87",
"value" : "5000"
}
],
"uncleHeaders" : [
]
},
{
"blockHeader" : {
"RelTimestamp" : "13"
},
"transactions" : [
{
"data" : "",
"gasLimit" : "50000",
"gasPrice" : "10",
"nonce" : "0",
"secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
"to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87",
"value" : "5000"
}
],
"uncleHeaders" : [
]
}
]
},
"timeDiff14" : {
"genesisBlockHeader" : {
"bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"coinbase" : "0x8888f1f195afa192cfee860698584c030f4c9db1",
"difficulty" : "231072",
"extraData" : "0x42",
"gasLimit" : "3141592",
"gasUsed" : "0",
"mixHash" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"nonce" : "0x0102030405060708",
"number" : "0",
"parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
"receiptTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"stateRoot" : "0xf99eb1626cfa6db435c0836235942d7ccaa935f1ae247d3f1c21e495685f903a",
"timestamp" : "0x54c98c81",
"transactionsTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"uncleHash" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
},
"expect" : {
"095e7baea6a6c7c4c2dfeb977efac326af552d87" : {
"balance" : "100"
}
},
"pre" : {
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
"balance" : "100000000000",
"nonce" : "0",
"code" : "",
"storage": {}
},
"095e7baea6a6c7c4c2dfeb977efac326af552d87" : {
"balance" : "100",
"nonce" : "0",
"code" : "{ (MSTORE 0 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) (LOG1 0 32 0) }",
"storage": {}
}
},
"blocks" : [
{
"transactions" : [
{
"data" : "",
"gasLimit" : "50000",
"gasPrice" : "10",
"nonce" : "0",
"secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
"to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87",
"value" : "5000"
}
],
"uncleHeaders" : [
]
},
{
"blockHeader" : {
"RelTimestamp" : "14"
},
"transactions" : [
{
"data" : "",
"gasLimit" : "50000",
"gasPrice" : "10",
"nonce" : "0",
"secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
"to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87",
"value" : "5000"
}
],
"uncleHeaders" : [
]
}
]
},
"timeDiff0" : {
"genesisBlockHeader" : {
"bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"coinbase" : "0x8888f1f195afa192cfee860698584c030f4c9db1",
"difficulty" : "231072",
"extraData" : "0x42",
"gasLimit" : "3141592",
"gasUsed" : "0",
"mixHash" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"nonce" : "0x0102030405060708",
"number" : "0",
"parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
"receiptTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"stateRoot" : "0xf99eb1626cfa6db435c0836235942d7ccaa935f1ae247d3f1c21e495685f903a",
"timestamp" : "0x54c98c81",
"transactionsTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"uncleHash" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
},
"expect" : {
"095e7baea6a6c7c4c2dfeb977efac326af552d87" : {
"balance" : "100"
}
},
"pre" : {
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
"balance" : "100000000000",
"nonce" : "0",
"code" : "",
"storage": {}
},
"095e7baea6a6c7c4c2dfeb977efac326af552d87" : {
"balance" : "100",
"nonce" : "0",
"code" : "{ (MSTORE 0 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) (LOG1 0 32 0) }",
"storage": {}
}
},
"blocks" : [
{
"transactions" : [
{
"data" : "",
"gasLimit" : "50000",
"gasPrice" : "10",
"nonce" : "0",
"secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
"to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87",
"value" : "5000"
}
],
"uncleHeaders" : [
]
},
{
"blockHeader" : {
"RelTimestamp" : "0"
},
"transactions" : [
{
"data" : "",
"gasLimit" : "50000",
"gasPrice" : "10",
"nonce" : "0",
"secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
"to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87",
"value" : "5000"
}
],
"uncleHeaders" : [
]
}
]
},
"diff1024" : {
"genesisBlockHeader" : {
"bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
@ -263,6 +559,9 @@
},
"blocks" : [
{
"blockHeader" : {
"gasLimit" : "3141592"
},
"transactions" : [
{
"data" : "",

13
test/libethereum/blockchain.cpp

@ -46,7 +46,7 @@ RLPStream createFullBlockFromHeader(BlockHeader const& _bi, bytes const& _txs =
mArray writeTransactionsToJson(Transactions const& txs);
mObject writeBlockHeaderToJson(mObject& _o, BlockHeader const& _bi);
void overwriteBlockHeader(BlockHeader& _current_BlockHeader, mObject& _blObj);
void overwriteBlockHeader(BlockHeader& _current_BlockHeader, mObject& _blObj, const BlockHeader& _parent);
void updatePoW(BlockHeader& _bi);
mArray importUncles(mObject const& _blObj, vector<BlockHeader>& _vBiUncles, vector<BlockHeader> const& _vBiBlocks, std::vector<blockSet> _blockSet);
@ -223,7 +223,7 @@ void doBlockchainTests(json_spirit::mValue& _v, bool _fillin)
}
if (blObj.count("blockHeader"))
overwriteBlockHeader(current_BlockHeader, blObj);
overwriteBlockHeader(current_BlockHeader, blObj, vBiBlocks[vBiBlocks.size()-1]);
if (blObj.count("blockHeader") && blObj["blockHeader"].get_obj().count("bruncle"))
current_BlockHeader.populateFromParent(vBiBlocks[vBiBlocks.size() -1]);
@ -664,7 +664,7 @@ bytes createBlockRLPFromFields(mObject& _tObj, h256 const& _stateRoot)
return rlpStream.out();
}
void overwriteBlockHeader(BlockHeader& _header, mObject& _blObj)
void overwriteBlockHeader(BlockHeader& _header, mObject& _blObj, BlockHeader const& _parent)
{
auto ho = _blObj["blockHeader"].get_obj();
if (ho.size() != 14)
@ -684,6 +684,13 @@ void overwriteBlockHeader(BlockHeader& _header, mObject& _blObj)
ho.count("timestamp") ? toInt(ho["timestamp"]) : _header.timestamp(),
ho.count("extraData") ? importByteArray(ho["extraData"].get_str()) : _header.extraData());
if (ho.count("RelTimestamp"))
{
tmp.setTimestamp(toInt(ho["RelTimestamp"]) +_parent.timestamp());
tmp.setDifficulty(tmp.calculateDifficulty(_parent));
this_thread::sleep_for(chrono::seconds((int)toInt(ho["RelTimestamp"])));
}
// find new valid nonce
if (static_cast<BlockInfo>(tmp) != static_cast<BlockInfo>(_header) && tmp.difficulty())
mine(tmp);

70
test/libevm/VMTestsFiller/vmIOandFlowOperationsTestFiller.json

@ -1372,6 +1372,76 @@
}
},
"loop_stacklimit_1020": {
"env" : {
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6",
"currentNumber" : "0",
"currentGasLimit" : "1000000",
"currentDifficulty" : "256",
"currentTimestamp" : "1",
"currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba"
},
"expect" : {
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
"storage" : {
"0x02" : "0x23"
}
}
},
"pre" : {
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
"balance" : "100000000000000000000000",
"nonce" : "0",
"code" : "(asm 0 CALLVALUE JUMPDEST 1 SWAP1 SUB SWAP1 1 ADD DUP2 DUP1 3 JUMPI 0 MSTORE 1 MSTORE 0 MSIZE RETURN)",
"storage": {}
}
},
"exec" : {
"address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6",
"origin" : "cd1722f3947def4cf144679da39c4c32bdc35681",
"caller" : "cd1722f3947def4cf144679da39c4c32bdc35681",
"value" : "1020",
"data" : "",
"gasPrice" : "100000000000000",
"gas" : "100000"
}
},
"loop_stacklimit_1021": {
"env" : {
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6",
"currentNumber" : "0",
"currentGasLimit" : "1000000",
"currentDifficulty" : "256",
"currentTimestamp" : "1",
"currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba"
},
"expect" : {
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
"storage" : {
"0x02" : "0x23"
}
}
},
"pre" : {
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
"balance" : "100000000000000000000000",
"nonce" : "0",
"code" : "(asm 0 CALLVALUE JUMPDEST 1 SWAP1 SUB SWAP1 1 ADD DUP2 DUP1 3 JUMPI 0 MSTORE 1 MSTORE 0 MSIZE RETURN)",
"storage": {}
}
},
"exec" : {
"address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6",
"origin" : "cd1722f3947def4cf144679da39c4c32bdc35681",
"caller" : "cd1722f3947def4cf144679da39c4c32bdc35681",
"value" : "1021",
"data" : "",
"gasPrice" : "100000000000000",
"gas" : "100000"
}
},
"jump0_withoutJumpdest": {
"env" : {
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6",

24
test/libp2p/rlpx.cpp

@ -455,12 +455,12 @@ BOOST_AUTO_TEST_CASE(ecies_interop_test_primitives)
BOOST_AUTO_TEST_CASE(segmentedPacketFlush)
{
ECDHE localEph;
h256 localNonce = Nonce::get();
Secret localNonce = Nonce::get();
ECDHE remoteEph;
h256 remoteNonce = Nonce::get();
Secret remoteNonce = Nonce::get();
bytes ackCipher{0};
bytes authCipher{1};
RLPXFrameCoder encoder(true, remoteEph.pubkey(), remoteNonce, localEph, localNonce, &ackCipher, &authCipher);
RLPXFrameCoder encoder(true, remoteEph.pubkey(), remoteNonce.makeInsecure(), localEph, localNonce.makeInsecure(), &ackCipher, &authCipher);
/// Test writing a 64byte RLPStream and drain with frame size that
/// forces packet to be pieced into 4 frames.
@ -506,7 +506,7 @@ BOOST_AUTO_TEST_CASE(segmentedPacketFlush)
}
// read and assemble dequed encframes
RLPXFrameCoder decoder(false, localEph.pubkey(), localNonce, remoteEph, remoteNonce, &ackCipher, &authCipher);
RLPXFrameCoder decoder(false, localEph.pubkey(), localNonce.makeInsecure(), remoteEph, remoteNonce.makeInsecure(), &ackCipher, &authCipher);
vector<RLPXPacket> packets;
RLPXFrameReader r(0);
for (size_t i = 0; i < encframes.size(); i++)
@ -529,12 +529,12 @@ BOOST_AUTO_TEST_CASE(segmentedPacketFlush)
BOOST_AUTO_TEST_CASE(coalescedPacketsPadded)
{
ECDHE localEph;
h256 localNonce = Nonce::get();
Secret localNonce = Nonce::get();
ECDHE remoteEph;
h256 remoteNonce = Nonce::get();
Secret remoteNonce = Nonce::get();
bytes ackCipher{0};
bytes authCipher{1};
RLPXFrameCoder encoder(true, remoteEph.pubkey(), remoteNonce, localEph, localNonce, &ackCipher, &authCipher);
RLPXFrameCoder encoder(true, remoteEph.pubkey(), remoteNonce.makeInsecure(), localEph, localNonce.makeInsecure(), &ackCipher, &authCipher);
/// Test writing four 32 byte RLPStream packets such that
/// a single 1KB frame will incldue all four packets.
@ -559,7 +559,7 @@ BOOST_AUTO_TEST_CASE(coalescedPacketsPadded)
BOOST_REQUIRE_EQUAL(expectedFrameSize, encframes[0].size());
// read and assemble dequed encframes
RLPXFrameCoder decoder(false, localEph.pubkey(), localNonce, remoteEph, remoteNonce, &ackCipher, &authCipher);
RLPXFrameCoder decoder(false, localEph.pubkey(), localNonce.makeInsecure(), remoteEph, remoteNonce.makeInsecure(), &ackCipher, &authCipher);
vector<RLPXPacket> packets;
RLPXFrameReader r(0);
bytesRef frameWithHeader(encframes[0].data(), encframes[0].size());
@ -587,12 +587,12 @@ BOOST_AUTO_TEST_CASE(coalescedPacketsPadded)
BOOST_AUTO_TEST_CASE(singleFramePacketFlush)
{
ECDHE localEph;
h256 localNonce = Nonce::get();
Secret localNonce = Nonce::get();
ECDHE remoteEph;
h256 remoteNonce = Nonce::get();
Secret remoteNonce = Nonce::get();
bytes ackCipher{0};
bytes authCipher{1};
RLPXFrameCoder encoder(true, remoteEph.pubkey(), remoteNonce, localEph, localNonce, &ackCipher, &authCipher);
RLPXFrameCoder encoder(true, remoteEph.pubkey(), remoteNonce.makeInsecure(), localEph, localNonce.makeInsecure(), &ackCipher, &authCipher);
/// Test writing four 32 byte RLPStream packets such that
/// a single 1KB frame will incldue all four packets.
@ -611,7 +611,7 @@ BOOST_AUTO_TEST_CASE(singleFramePacketFlush)
BOOST_REQUIRE_EQUAL(dequeLen, encframes[0].size());
// read and assemble dequed encframes
RLPXFrameCoder decoder(false, localEph.pubkey(), localNonce, remoteEph, remoteNonce, &ackCipher, &authCipher);
RLPXFrameCoder decoder(false, localEph.pubkey(), localNonce.makeInsecure(), remoteEph, remoteNonce.makeInsecure(), &ackCipher, &authCipher);
vector<RLPXPacket> packets;
RLPXFrameReader r(0);
bytesRef frameWithHeader(encframes[0].data(), encframes[0].size());

237
test/libsolidity/SolidityFixedFeeRegistrar.cpp

@ -0,0 +1,237 @@
/*
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/>.
*/
/**
* @author Christian <c@ethdev.com>
* @date 2015
* Tests for a fixed fee registrar contract.
*/
#include <string>
#include <tuple>
#include <boost/test/unit_test.hpp>
#include <libdevcore/Hash.h>
#include <test/libsolidity/solidityExecutionFramework.h>
using namespace std;
namespace dev
{
namespace solidity
{
namespace test
{
static char const* registrarCode = R"DELIMITER(
//sol FixedFeeRegistrar
// Simple global registrar with fixed-fee reservations.
// @authors:
// Gav Wood <g@ethdev.com>
contract Registrar {
event Changed(string indexed name);
function owner(string _name) constant returns (address o_owner);
function addr(string _name) constant returns (address o_address);
function subRegistrar(string _name) constant returns (address o_subRegistrar);
function content(string _name) constant returns (bytes32 o_content);
}
contract FixedFeeRegistrar is Registrar {
struct Record {
address addr;
address subRegistrar;
bytes32 content;
address owner;
}
modifier onlyrecordowner(string _name) { if (m_record(_name).owner == msg.sender) _ }
function reserve(string _name) {
Record rec = m_record(_name);
if (rec.owner == 0 && msg.value >= c_fee) {
rec.owner = msg.sender;
Changed(_name);
}
}
function disown(string _name, address _refund) onlyrecordowner(_name) {
delete m_recordData[uint(sha3(_name)) / 8];
_refund.send(c_fee);
Changed(_name);
}
function transfer(string _name, address _newOwner) onlyrecordowner(_name) {
m_record(_name).owner = _newOwner;
Changed(_name);
}
function setAddr(string _name, address _a) onlyrecordowner(_name) {
m_record(_name).addr = _a;
Changed(_name);
}
function setSubRegistrar(string _name, address _registrar) onlyrecordowner(_name) {
m_record(_name).subRegistrar = _registrar;
Changed(_name);
}
function setContent(string _name, bytes32 _content) onlyrecordowner(_name) {
m_record(_name).content = _content;
Changed(_name);
}
function record(string _name) constant returns (address o_addr, address o_subRegistrar, bytes32 o_content, address o_owner) {
Record rec = m_record(_name);
o_addr = rec.addr;
o_subRegistrar = rec.subRegistrar;
o_content = rec.content;
o_owner = rec.owner;
}
function addr(string _name) constant returns (address) { return m_record(_name).addr; }
function subRegistrar(string _name) constant returns (address) { return m_record(_name).subRegistrar; }
function content(string _name) constant returns (bytes32) { return m_record(_name).content; }
function owner(string _name) constant returns (address) { return m_record(_name).owner; }
Record[2**253] m_recordData;
function m_record(string _name) constant internal returns (Record storage o_record) {
return m_recordData[uint(sha3(_name)) / 8];
}
uint constant c_fee = 69 ether;
}
)DELIMITER";
static unique_ptr<bytes> s_compiledRegistrar;
class RegistrarTestFramework: public ExecutionFramework
{
protected:
void deployRegistrar()
{
if (!s_compiledRegistrar)
{
m_optimize = true;
m_compiler.reset(false, m_addStandardSources);
m_compiler.addSource("", registrarCode);
ETH_TEST_REQUIRE_NO_THROW(m_compiler.compile(m_optimize, m_optimizeRuns), "Compiling contract failed");
s_compiledRegistrar.reset(new bytes(m_compiler.getBytecode("FixedFeeRegistrar")));
}
sendMessage(*s_compiledRegistrar, true);
BOOST_REQUIRE(!m_output.empty());
}
u256 const m_fee = u256("69000000000000000000");
};
/// This is a test suite that tests optimised code!
BOOST_FIXTURE_TEST_SUITE(SolidityFixedFeeRegistrar, RegistrarTestFramework)
BOOST_AUTO_TEST_CASE(creation)
{
deployRegistrar();
}
BOOST_AUTO_TEST_CASE(reserve)
{
// Test that reserving works and fee is taken into account.
deployRegistrar();
string name[] = {"abc", "def", "ghi"};
m_sender = Address(0x123);
BOOST_REQUIRE(callContractFunctionWithValue("reserve(string)", m_fee, encodeDyn(name[0])) == encodeArgs());
BOOST_CHECK(callContractFunction("owner(string)", encodeDyn(name[0])) == encodeArgs(h256(0x123)));
BOOST_REQUIRE(callContractFunctionWithValue("reserve(string)", m_fee + 1, encodeDyn(name[1])) == encodeArgs());
BOOST_CHECK(callContractFunction("owner(string)", encodeDyn(name[1])) == encodeArgs(h256(0x123)));
BOOST_REQUIRE(callContractFunctionWithValue("reserve(string)", m_fee - 1, encodeDyn(name[2])) == encodeArgs());
BOOST_CHECK(callContractFunction("owner(string)", encodeDyn(name[2])) == encodeArgs(h256(0)));
}
BOOST_AUTO_TEST_CASE(double_reserve)
{
// Test that it is not possible to re-reserve from a different address.
deployRegistrar();
string name = "abc";
m_sender = Address(0x123);
BOOST_REQUIRE(callContractFunctionWithValue("reserve(string)", m_fee, encodeDyn(name)) == encodeArgs());
BOOST_CHECK(callContractFunction("owner(string)", encodeDyn(name)) == encodeArgs(h256(0x123)));
m_sender = Address(0x124);
BOOST_REQUIRE(callContractFunctionWithValue("reserve(string)", m_fee, encodeDyn(name)) == encodeArgs());
BOOST_CHECK(callContractFunction("owner(string)", encodeDyn(name)) == encodeArgs(h256(0x123)));
}
BOOST_AUTO_TEST_CASE(properties)
{
// Test setting and retrieving the various properties works.
deployRegistrar();
string names[] = {"abc", "def", "ghi"};
size_t addr = 0x9872543;
for (string const& name: names)
{
addr++;
size_t sender = addr + 10007;
m_sender = Address(sender);
// setting by sender works
BOOST_REQUIRE(callContractFunctionWithValue("reserve(string)", m_fee, encodeDyn(name)) == encodeArgs());
BOOST_CHECK(callContractFunction("owner(string)", encodeDyn(name)) == encodeArgs(u256(sender)));
BOOST_CHECK(callContractFunction("setAddr(string,address)", u256(0x40), u256(addr), u256(name.length()), name) == encodeArgs());
BOOST_CHECK(callContractFunction("addr(string)", encodeDyn(name)) == encodeArgs(addr));
BOOST_CHECK(callContractFunction("setSubRegistrar(string,address)", u256(0x40), addr + 20, u256(name.length()), name) == encodeArgs());
BOOST_CHECK(callContractFunction("subRegistrar(string)", encodeDyn(name)) == encodeArgs(addr + 20));
BOOST_CHECK(callContractFunction("setContent(string,bytes32)", u256(0x40), addr + 90, u256(name.length()), name) == encodeArgs());
BOOST_CHECK(callContractFunction("content(string)", encodeDyn(name)) == encodeArgs(addr + 90));
// but not by someone else
m_sender = Address(h256(addr + 10007 - 1));
BOOST_CHECK(callContractFunction("owner(string)", encodeDyn(name)) == encodeArgs(sender));
BOOST_CHECK(callContractFunction("setAddr(string,address)", u256(0x40), addr + 1, u256(name.length()), name) == encodeArgs());
BOOST_CHECK(callContractFunction("addr(string)", encodeDyn(name)) == encodeArgs(addr));
BOOST_CHECK(callContractFunction("setSubRegistrar(string,address)", u256(0x40), addr + 20 + 1, u256(name.length()), name) == encodeArgs());
BOOST_CHECK(callContractFunction("subRegistrar(string)", encodeDyn(name)) == encodeArgs(addr + 20));
BOOST_CHECK(callContractFunction("setContent(string,bytes32)", u256(0x40), addr + 90 + 1, u256(name.length()), name) == encodeArgs());
BOOST_CHECK(callContractFunction("content(string)", encodeDyn(name)) == encodeArgs(addr + 90));
}
}
BOOST_AUTO_TEST_CASE(transfer)
{
deployRegistrar();
string name = "abc";
m_sender = Address(0x123);
BOOST_REQUIRE(callContractFunctionWithValue("reserve(string)", m_fee, encodeDyn(name)) == encodeArgs());
BOOST_CHECK(callContractFunction("setContent(string,bytes32)", u256(0x40), u256(123), u256(name.length()), name) == encodeArgs());
BOOST_CHECK(callContractFunction("transfer(string,address)", u256(0x40), u256(555), u256(name.length()), name) == encodeArgs());
BOOST_CHECK(callContractFunction("owner(string)", encodeDyn(name)) == encodeArgs(u256(555)));
BOOST_CHECK(callContractFunction("content(string)", encodeDyn(name)) == encodeArgs(u256(123)));
}
BOOST_AUTO_TEST_CASE(disown)
{
deployRegistrar();
string name = "abc";
m_sender = Address(0x123);
BOOST_REQUIRE(callContractFunctionWithValue("reserve(string)", m_fee, encodeDyn(name)) == encodeArgs());
BOOST_CHECK(callContractFunction("setContent(string,bytes32)", u256(0x40), u256(123), u256(name.length()), name) == encodeArgs());
BOOST_CHECK(callContractFunction("setAddr(string,address)", u256(0x40), u256(124), u256(name.length()), name) == encodeArgs());
BOOST_CHECK(callContractFunction("setSubRegistrar(string,address)", u256(0x40), u256(125), u256(name.length()), name) == encodeArgs());
BOOST_CHECK_EQUAL(m_state.balance(Address(0x124)), 0);
BOOST_CHECK(callContractFunction("disown(string,address)", u256(0x40), u256(0x124), name.size(), name) == encodeArgs());
BOOST_CHECK_EQUAL(m_state.balance(Address(0x124)), m_fee);
BOOST_CHECK(callContractFunction("owner(string)", encodeDyn(name)) == encodeArgs(u256(0)));
BOOST_CHECK(callContractFunction("content(string)", encodeDyn(name)) == encodeArgs(u256(0)));
BOOST_CHECK(callContractFunction("addr(string)", encodeDyn(name)) == encodeArgs(u256(0)));
BOOST_CHECK(callContractFunction("subRegistrar(string)", encodeDyn(name)) == encodeArgs(u256(0)));
}
BOOST_AUTO_TEST_SUITE_END()
}
}
} // end namespaces

1
test/libsolidity/solidityExecutionFramework.h

@ -130,6 +130,7 @@ public:
static bytes encode(bool _value) { return encode(byte(_value)); }
static bytes encode(int _value) { return encode(u256(_value)); }
static bytes encode(size_t _value) { return encode(u256(_value)); }
static bytes encode(char const* _value) { return encode(std::string(_value)); }
static bytes encode(byte _value) { return bytes(31, 0) + bytes{_value}; }
static bytes encode(u256 const& _value) { return toBigEndian(_value); }

66
test/libwhisper/whisperTopic.cpp

@ -57,6 +57,8 @@ BOOST_AUTO_TEST_CASE(topic)
bool host1Ready = false;
unsigned result = 0;
unsigned const step = 10;
std::thread listener([&]()
{
setThreadName("other");
@ -86,21 +88,30 @@ BOOST_AUTO_TEST_CASE(topic)
auto whost2 = host2.registerCapability(new WhisperHost());
host2.start();
while (!host1.haveNetwork())
this_thread::sleep_for(chrono::milliseconds(5));
for (unsigned i = 0; i < 3000 && (!host1.haveNetwork() || !host2.haveNetwork()); i += step)
this_thread::sleep_for(chrono::milliseconds(step));
BOOST_REQUIRE(host1.haveNetwork());
BOOST_REQUIRE(host2.haveNetwork());
host2.addNode(host1.id(), NodeIPEndpoint(bi::address::from_string("127.0.0.1"), port1, port1));
// wait for nodes to connect
this_thread::sleep_for(chrono::milliseconds(1000));
for (unsigned i = 0; i < 3000 && (!host1.peerCount() || !host2.peerCount()); i += step)
this_thread::sleep_for(chrono::milliseconds(step));
while (!host1Ready)
this_thread::sleep_for(chrono::milliseconds(10));
BOOST_REQUIRE(host1.peerCount());
BOOST_REQUIRE(host2.peerCount());
for (unsigned i = 0; i < 3000 && !host1Ready; i += step)
this_thread::sleep_for(chrono::milliseconds(step));
BOOST_REQUIRE(host1Ready);
KeyPair us = KeyPair::create();
for (int i = 0; i < 10; ++i)
{
whost2->post(us.sec(), RLPStream().append(i * i).out(), BuildTopic(i)(i % 2 ? "odd" : "even"));
this_thread::sleep_for(chrono::milliseconds(250));
this_thread::sleep_for(chrono::milliseconds(50));
}
listener.join();
@ -314,59 +325,54 @@ BOOST_AUTO_TEST_CASE(topicAdvertising)
while (!host1.haveNetwork())
this_thread::sleep_for(chrono::milliseconds(10));
unsigned const step = 10;
uint16_t port2 = 30318;
Host host2("second", NetworkPreferences("127.0.0.1", port2, false));
host2.setIdealPeerCount(1);
auto whost2 = host2.registerCapability(new WhisperHost());
unsigned w2 = whost2->installWatch(BuildTopicMask("test2"));
host2.start();
while (!host2.haveNetwork())
this_thread::sleep_for(chrono::milliseconds(10));
host1.addNode(host2.id(), NodeIPEndpoint(bi::address::from_string("127.0.0.1"), port2, port2));
while (!host1.haveNetwork())
this_thread::sleep_for(chrono::milliseconds(10));
for (unsigned i = 0; i < 3000 && (!host1.haveNetwork() || !host2.haveNetwork()); i += step)
this_thread::sleep_for(chrono::milliseconds(step));
while (!host1.peerCount())
this_thread::sleep_for(chrono::milliseconds(10));
host1.addNode(host2.id(), NodeIPEndpoint(bi::address::from_string("127.0.0.1"), port2, port2));
while (!host2.peerCount())
this_thread::sleep_for(chrono::milliseconds(10));
for (unsigned i = 0; i < 3000 && (!host1.peerCount() || !host2.peerCount()); i += step)
this_thread::sleep_for(chrono::milliseconds(step));
std::vector<std::pair<std::shared_ptr<Session>, std::shared_ptr<Peer>>> sessions;
TopicBloomFilterHash bf1;
for (int i = 0; i < 600; ++i)
for (int i = 0; i < 600 && !bf1; ++i)
{
sessions = whost1->peerSessions();
if (!sessions.empty() && sessions.back().first->cap<WhisperPeer>()->bloom())
break;
else
this_thread::sleep_for(chrono::milliseconds(10));
if (!sessions.empty())
bf1 = sessions.back().first->cap<WhisperPeer>()->bloom();
this_thread::sleep_for(chrono::milliseconds(step));
}
BOOST_REQUIRE(sessions.size());
TopicBloomFilterHash bf1 = sessions.back().first->cap<WhisperPeer>()->bloom();
TopicBloomFilterHash bf2 = whost2->bloom();
BOOST_REQUIRE_EQUAL(bf1, bf2);
BOOST_REQUIRE(bf1);
BOOST_REQUIRE(!whost1->bloom());
unsigned w1 = whost1->installWatch(BuildTopicMask("test1"));
bf2 = TopicBloomFilterHash();
for (int i = 0; i < 600; ++i)
for (int i = 0; i < 600 && !bf2; ++i)
{
sessions = whost2->peerSessions();
if (!sessions.empty() && sessions.back().first->cap<WhisperPeer>()->bloom())
break;
else
this_thread::sleep_for(chrono::milliseconds(10));
if (!sessions.empty())
bf2 = sessions.back().first->cap<WhisperPeer>()->bloom();
this_thread::sleep_for(chrono::milliseconds(step));
}
BOOST_REQUIRE(sessions.size());
BOOST_REQUIRE_EQUAL(sessions.back().second->id, host1.id());
bf2 = sessions.back().first->cap<WhisperPeer>()->bloom();
bf1 = whost1->bloom();
BOOST_REQUIRE_EQUAL(bf1, bf2);
BOOST_REQUIRE(bf1);

Loading…
Cancel
Save