Browse Source

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

cl-refactor
arkpar 10 years ago
parent
commit
87c74bbc75
  1. 5
      CMakeLists.txt
  2. 2
      alethzero/DappLoader.cpp
  3. 20
      ethminer/MinerAux.h
  4. 8
      libdevcore/CommonIO.cpp
  5. 2
      libdevcore/RLP.h
  6. 4
      libethcore/BlockInfo.cpp
  7. 7
      libethcore/EthashAux.cpp
  8. 2
      libethcore/EthashAux.h
  9. 16
      libethcore/ICAP.cpp
  10. 2
      libethcore/KeyManager.h
  11. 1
      libethereum/EthereumHost.cpp
  12. 2
      libethereum/State.cpp
  13. 120
      libjsqrc/admin.js
  14. 8
      libjsqrc/ethereumjs/LICENSE
  15. 2
      libjsqrc/ethereumjs/README.md
  16. 2
      libjsqrc/ethereumjs/bower.json
  17. 5683
      libjsqrc/ethereumjs/dist/web3-light.js
  18. 2
      libjsqrc/ethereumjs/dist/web3-light.min.js
  19. 260
      libjsqrc/ethereumjs/dist/web3.js
  20. 85
      libjsqrc/ethereumjs/dist/web3.js.map
  21. 4
      libjsqrc/ethereumjs/dist/web3.min.js
  22. 153
      libjsqrc/ethereumjs/example/coin.html
  23. 5
      libjsqrc/ethereumjs/example/event_inc.html
  24. 2
      libjsqrc/ethereumjs/gulpfile.js
  25. 2
      libjsqrc/ethereumjs/lib/utils/config.js
  26. 2
      libjsqrc/ethereumjs/lib/version.json
  27. 33
      libjsqrc/ethereumjs/lib/web3.js
  28. 10
      libjsqrc/ethereumjs/lib/web3/eth.js
  29. 99
      libjsqrc/ethereumjs/lib/web3/filter.js
  30. 22
      libjsqrc/ethereumjs/lib/web3/formatters.js
  31. 13
      libjsqrc/ethereumjs/lib/web3/function.js
  32. 4
      libjsqrc/ethereumjs/lib/web3/httpprovider.js
  33. 1
      libjsqrc/ethereumjs/lib/web3/property.js
  34. 59
      libjsqrc/ethereumjs/lib/web3/requestmanager.js
  35. 4
      libjsqrc/ethereumjs/lib/web3/watches.js
  36. 2
      libjsqrc/ethereumjs/package.js
  37. 6
      libjsqrc/ethereumjs/package.json
  38. 55
      libjsqrc/ethereumjs/test/contract.js
  39. 70
      libjsqrc/ethereumjs/test/formatters.outputBlockFormatter.js
  40. 32
      libjsqrc/ethereumjs/test/formatters.outputLogFormatter.js
  41. 35
      libjsqrc/ethereumjs/test/formatters.outputTransactionFormatter.js
  42. 10
      libjsqrc/ethereumjs/test/helpers/FakeHttpProvider2.js
  43. 7
      libjsqrc/ethereumjs/test/helpers/FakeXMLHttpRequest.js
  44. 76
      libjsqrc/ethereumjs/test/web3.extend.js
  45. 1
      libjsqrc/js.qrc
  46. 26
      libsolidity/ArrayUtils.cpp
  47. 15
      libsolidity/Compiler.cpp
  48. 2
      libsolidity/CompilerUtils.cpp
  49. 13
      libsolidity/ExpressionCompiler.cpp
  50. 40
      libsolidity/Types.cpp
  51. 24
      libsolidity/Types.h
  52. BIN
      mix/qml/img/edittransaction.png
  53. BIN
      mix/qml/img/edittransaction2.png
  54. BIN
      mix/qml/img/edittransaction2@2x.png
  55. BIN
      mix/qml/img/edittransaction@2x.png
  56. BIN
      mix/qml/img/newblock.png
  57. BIN
      mix/qml/img/newblock@2x.png
  58. 55
      test/TestHelper.cpp
  59. 4
      test/TestHelper.h
  60. 123
      test/fuzzTesting/createRandomTest.cpp
  61. 40
      test/libethereum/StateTestsFiller/stSystemOperationsTestFiller.json
  62. 2
      test/libethereum/state.cpp
  63. 4
      test/libethereum/transaction.cpp
  64. 6
      test/libevm/vm.cpp
  65. 162
      test/libsolidity/SolidityEndToEndTest.cpp
  66. 13
      test/libsolidity/SolidityNameAndTypeResolution.cpp

5
CMakeLists.txt

@ -84,7 +84,10 @@ function(configureProject)
add_definitions(-DETH_CURL)
endif()
add_definitions(-DNOBOOST)
if (NOBOOST)
add_definitions(-DNOBOOST)
endif()
add_definitions(-DETH_TRUE)
endfunction()

2
alethzero/DappLoader.cpp

@ -193,6 +193,8 @@ QByteArray const& DappLoader::web3Content()
code += "\n";
code += contentsOfQResource(":/js/setup.js");
code += "\n";
code += contentsOfQResource(":/js/admin.js");
code += "\n";
m_web3Js = code.toLatin1();
}
return m_web3Js;

20
ethminer/MinerAux.h

@ -107,7 +107,7 @@ public:
catch (...)
{
cerr << "Bad " << arg << " option: " << argv[i] << endl;
throw BadArgument();
BOOST_THROW_EXCEPTION(BadArgument());
}
else if (arg == "--opencl-platform" && i + 1 < argc)
try {
@ -116,7 +116,7 @@ public:
catch (...)
{
cerr << "Bad " << arg << " option: " << argv[i] << endl;
throw BadArgument();
BOOST_THROW_EXCEPTION(BadArgument());
}
else if (arg == "--opencl-device" && i + 1 < argc)
try {
@ -126,7 +126,7 @@ public:
catch (...)
{
cerr << "Bad " << arg << " option: " << argv[i] << endl;
throw BadArgument();
BOOST_THROW_EXCEPTION(BadArgument());
}
else if (arg == "--list-devices")
m_shouldListDevices = true;
@ -144,7 +144,7 @@ public:
else
{
cerr << "Bad " << arg << " option: " << m << endl;
throw BadArgument();
BOOST_THROW_EXCEPTION(BadArgument());
}
}
else if (arg == "--benchmark-warmup" && i + 1 < argc)
@ -154,7 +154,7 @@ public:
catch (...)
{
cerr << "Bad " << arg << " option: " << argv[i] << endl;
throw BadArgument();
BOOST_THROW_EXCEPTION(BadArgument());
}
else if (arg == "--benchmark-trial" && i + 1 < argc)
try {
@ -163,7 +163,7 @@ public:
catch (...)
{
cerr << "Bad " << arg << " option: " << argv[i] << endl;
throw BadArgument();
BOOST_THROW_EXCEPTION(BadArgument());
}
else if (arg == "--benchmark-trials" && i + 1 < argc)
try {
@ -172,7 +172,7 @@ public:
catch (...)
{
cerr << "Bad " << arg << " option: " << argv[i] << endl;
throw BadArgument();
BOOST_THROW_EXCEPTION(BadArgument());
}
else if (arg == "-C" || arg == "--cpu")
m_minerType = MinerType::CPU;
@ -195,7 +195,7 @@ public:
catch (...)
{
cerr << "Bad " << arg << " option: " << m << endl;
throw BadArgument();
BOOST_THROW_EXCEPTION(BadArgument());
}
}
else if ((arg == "-w" || arg == "--check-pow") && i + 4 < argc)
@ -232,7 +232,7 @@ public:
catch (...)
{
cerr << "Bad " << arg << " option: " << m << endl;
throw BadArgument();
BOOST_THROW_EXCEPTION(BadArgument());
}
}
else if (arg == "-M" || arg == "--benchmark")
@ -245,7 +245,7 @@ public:
catch (...)
{
cerr << "Bad " << arg << " option: " << argv[i] << endl;
throw BadArgument();
BOOST_THROW_EXCEPTION(BadArgument());
}
}
else

8
libdevcore/CommonIO.cpp

@ -98,9 +98,9 @@ string dev::contentsString(string const& _file)
void dev::writeFile(std::string const& _file, bytesConstRef _data, bool _writeDeleteRename)
{
namespace fs = boost::filesystem;
if (_writeDeleteRename)
{
namespace fs = boost::filesystem;
fs::path tempPath = fs::unique_path(_file + "-%%%%%%");
writeFile(tempPath.string(), _data, false);
// will delete _file if it exists
@ -108,10 +108,14 @@ void dev::writeFile(std::string const& _file, bytesConstRef _data, bool _writeDe
}
else
{
// create directory if not existent
fs::path p(_file);
fs::create_directories(p.parent_path());
ofstream s(_file, ios::trunc | ios::binary);
s.write(reinterpret_cast<char const*>(_data.data()), _data.size());
if (!s)
BOOST_THROW_EXCEPTION(FileError());
BOOST_THROW_EXCEPTION(FileError() << errinfo_comment("Could not write to file: " + _file));
}
}

2
libdevcore/RLP.h

@ -292,7 +292,7 @@ public:
RLPs toList() const;
/// @returns the data payload. Valid for all types.
bytesConstRef payload() const { auto l = length(); if (l > m_data.size()) throw BadRLP(); return m_data.cropped(payloadOffset(), l); }
bytesConstRef payload() const { auto l = length(); if (l > m_data.size()) BOOST_THROW_EXCEPTION(BadRLP()); return m_data.cropped(payloadOffset(), l); }
/// @returns the theoretical size of this item.
/// @note Under normal circumstances, is equivalent to m_data.size() - use that unless you know it won't work.

4
libethcore/BlockInfo.cpp

@ -122,7 +122,7 @@ void BlockInfo::populateFromHeader(RLP const& _header, Strictness _s, h256 const
try
{
if (_header.itemCount() != 15)
throw InvalidBlockHeaderItemCount();
BOOST_THROW_EXCEPTION(InvalidBlockHeaderItemCount());
parentHash = _header[field = 0].toHash<h256>(RLP::VeryStrict);
sha3Uncles = _header[field = 1].toHash<h256>(RLP::VeryStrict);
coinbaseAddress = _header[field = 2].toHash<Address>(RLP::VeryStrict);
@ -146,7 +146,7 @@ void BlockInfo::populateFromHeader(RLP const& _header, Strictness _s, h256 const
}
if (number > ~(unsigned)0)
throw InvalidNumber();
BOOST_THROW_EXCEPTION(InvalidNumber());
// check it hashes according to proof of work or that it's the genesis block.
if (_s == CheckEverything && parentHash && !ProofOfWork::verify(*this))

7
libethcore/EthashAux.cpp

@ -49,6 +49,13 @@ EthashAux::~EthashAux()
{
}
EthashAux* EthashAux::get()
{
static std::once_flag flag;
std::call_once(flag, []{s_this = new EthashAux();});
return s_this;
}
uint64_t EthashAux::cacheSize(BlockInfo const& _header)
{
return ethash_get_cachesize((uint64_t)_header.number);

2
libethcore/EthashAux.h

@ -38,7 +38,7 @@ class EthashAux
public:
~EthashAux();
static EthashAux* get() { if (!s_this) s_this = new EthashAux(); return s_this; }
static EthashAux* get();
struct LightAllocation
{

16
libethcore/ICAP.cpp

@ -71,7 +71,7 @@ ICAP ICAP::decoded(std::string const& _encoded)
std::string data;
std::tie(country, data) = fromIBAN(_encoded);
if (country != "XE")
throw InvalidICAP();
BOOST_THROW_EXCEPTION(InvalidICAP());
if (data.size() == 30)
{
ret.m_type = Direct;
@ -88,10 +88,10 @@ ICAP ICAP::decoded(std::string const& _encoded)
ret.m_client = data.substr(7);
}
else
throw InvalidICAP();
BOOST_THROW_EXCEPTION(InvalidICAP());
}
else
throw InvalidICAP();
BOOST_THROW_EXCEPTION(InvalidICAP());
return ret;
}
@ -101,7 +101,7 @@ std::string ICAP::encoded() const
if (m_type == Direct)
{
if (!!m_direct[0])
throw InvalidICAP();
BOOST_THROW_EXCEPTION(InvalidICAP());
std::string d = toBase36<Address::size>(m_direct);
while (d.size() < 30)
d = "0" + d;
@ -118,11 +118,11 @@ std::string ICAP::encoded() const
m_institution.size() != 4 ||
m_client.size() != 9
)
throw InvalidICAP();
BOOST_THROW_EXCEPTION(InvalidICAP());
return iban("XE", m_asset + m_institution + m_client);
}
else
throw InvalidICAP();
BOOST_THROW_EXCEPTION(InvalidICAP());
}
pair<Address, bytes> ICAP::lookup(std::function<bytes(Address, bytes)> const& _call, Address const& _reg) const
@ -149,9 +149,9 @@ pair<Address, bytes> ICAP::lookup(std::function<bytes(Address, bytes)> const& _c
else if (m_institution[0] != 'X')
return make_pair(resolve(m_institution + "/" + m_client), bytes());
else
throw InterfaceNotSupported("ICAP::lookup(), bad institution");
BOOST_THROW_EXCEPTION(InterfaceNotSupported("ICAP::lookup(), bad institution"));
}
throw InterfaceNotSupported("ICAP::lookup(), bad asset");
BOOST_THROW_EXCEPTION(InterfaceNotSupported("ICAP::lookup(), bad asset"));
}
}

2
libethcore/KeyManager.h

@ -46,7 +46,7 @@ struct KeyInfo
static h256 const UnknownPassword;
/// Password query function that never returns a password.
static auto const DontKnowThrow = [](){ throw PasswordUnknown(); return std::string(); };
static auto const DontKnowThrow = [](){ BOOST_THROW_EXCEPTION(PasswordUnknown()); return std::string(); };
enum class SemanticPassword
{

1
libethereum/EthereumHost.cpp

@ -41,7 +41,6 @@ using namespace dev::eth;
using namespace p2p;
unsigned const EthereumHost::c_oldProtocolVersion = 60; //TODO: remove this once v61+ is common
unsigned const c_chainReorgSize = 30000;
char const* const EthereumHost::s_stateNames[static_cast<int>(SyncState::Size)] = {"Idle", "Waiting", "Hashes", "Blocks", "NewBlocks" };

2
libethereum/State.cpp

@ -456,7 +456,7 @@ unordered_map<Address, u256> State::addresses() const
ret[i.first] = RLP(i.second)[1].toInt<u256>();
return ret;
#else
throw InterfaceNotSupported("State::addresses()");
BOOST_THROW_EXCEPTION(InterfaceNotSupported("State::addresses()"));
#endif
}

120
libjsqrc/admin.js

@ -0,0 +1,120 @@
web3.admin = {};
web3.admin.setSessionKey = function(s) { web3.admin.sessionKey = s; };
var getSessionKey = function () { return web3.admin.sessionKey; };
web3._extend({
property: 'admin',
methods: [new web3._extend.Method({
name: 'web3.setVerbosity',
call: 'admin_web3_setVerbosity',
inputFormatter: [null, getSessionKey],
params: 2
}), new web3._extend.Method({
name: 'net.start',
call: 'admin_net_start',
inputFormatter: [getSessionKey],
params: 1
}), new web3._extend.Method({
name: 'net.stop',
call: 'admin_net_stop',
inputFormatter: [getSessionKey],
params: 1
}), new web3._extend.Method({
name: 'net.connect',
call: 'admin_net_connect',
inputFormatter: [null, getSessionKey],
params: 2
}), new web3._extend.Method({
name: 'net.peers',
call: 'admin_net_peers',
inputFormatter: [getSessionKey],
params: 1
}), new web3._extend.Method({
name: 'eth.blockQueueStatus',
call: 'admin_eth_blockQueueStatus',
inputFormatter: [getSessionKey],
params: 1
}), new web3._extend.Method({
name: 'eth.setAskPrice',
call: 'admin_eth_setAskPrice',
inputFormatter: [null, getSessionKey],
params: 2
}), new web3._extend.Method({
name: 'eth.setBidPrice',
call: 'admin_eth_setBidPrice',
inputFormatter: [null, getSessionKey],
params: 2
}), new web3._extend.Method({
name: 'eth.setReferencePrice',
call: 'admin_eth_setReferencePrice',
inputFormatter: [null, getSessionKey],
params: 2
}), new web3._extend.Method({
name: 'eth.setPriority',
call: 'admin_eth_setPriority',
inputFormatter: [null, getSessionKey],
params: 2
}), new web3._extend.Method({
name: 'eth.setMining',
call: 'admin_eth_setMining',
inputFormatter: [null, getSessionKey],
params: 2
}), new web3._extend.Method({
name: 'eth.findBlock',
call: 'admin_eth_findBlock',
inputFormatter: [null, getSessionKey],
params: 2
}), new web3._extend.Method({
name: 'eth.blockQueueFirstUnknown',
call: 'admin_eth_blockQueueFirstUnknown',
inputFormatter: [getSessionKey],
params: 1
}), new web3._extend.Method({
name: 'eth.blockQueueRetryUnknown',
call: 'admin_eth_blockQueueRetryUnknown',
inputFormatter: [getSessionKey],
params: 1
}), new web3._extend.Method({
name: 'eth.allAccounts',
call: 'admin_eth_allAccounts',
inputFormatter: [getSessionKey],
params: 1
}), new web3._extend.Method({
name: 'eth.newAccount',
call: 'admin_eth_newAccount',
inputFormatter: [null, getSessionKey],
params: 2
}), new web3._extend.Method({
name: 'eth.setSigningKey',
call: 'admin_eth_setSigningKey',
inputFormatter: [null, getSessionKey],
params: 2
}), new web3._extend.Method({
name: 'eth.setMiningBenefactor',
call: 'admin_eth_setMiningBenefactor',
inputFormatter: [null, getSessionKey],
params: 2
}), new web3._extend.Method({
name: 'eth.inspect',
call: 'admin_eth_inspect',
inputFormatter: [null, getSessionKey],
params: 2
}), new web3._extend.Method({
name: 'eth.reprocess',
call: 'admin_eth_reprocess',
inputFormatter: [null, getSessionKey],
params: 2
}), new web3._extend.Method({
name: 'eth.vmTrace',
call: 'admin_eth_vmTrace',
inputFormatter: [null, null, getSessionKey],
params: 3
}), new web3._extend.Method({
name: 'eth.getReceiptByHashAndIndex',
call: 'admin_eth_getReceiptByHashAndIndex',
inputFormatter: [null, null, getSessionKey],
params: 3
})]
});

8
libjsqrc/ethereumjs/LICENSE

@ -1,14 +1,14 @@
This file is part of ethereum.js.
This file is part of web3.js.
ethereum.js is free software: you can redistribute it and/or modify
web3.js is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
ethereum.js is distributed in the hope that it will be useful,
web3.js 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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with ethereum.js. If not, see <http://www.gnu.org/licenses/>.
along with web3.js. If not, see <http://www.gnu.org/licenses/>.

2
libjsqrc/ethereumjs/README.md

@ -108,7 +108,7 @@ eth -j
[travis-url]: https://travis-ci.org/ethereum/web3.js
[dep-image]: https://david-dm.org/ethereum/web3.js.svg
[dep-url]: https://david-dm.org/ethereum/web3.js
[dep-dev-image]: https://david-dm.org/ethereum/web.js/dev-status.svg
[dep-dev-image]: https://david-dm.org/ethereum/web3.js/dev-status.svg
[dep-dev-url]: https://david-dm.org/ethereum/web3.js#info=devDependencies
[coveralls-image]: https://coveralls.io/repos/ethereum/web3.js/badge.svg?branch=master
[coveralls-url]: https://coveralls.io/r/ethereum/web3.js?branch=master

2
libjsqrc/ethereumjs/bower.json

@ -1,7 +1,7 @@
{
"name": "web3",
"namespace": "ethereum",
"version": "0.5.0",
"version": "0.6.0",
"description": "Ethereum Compatible JavaScript API",
"main": [
"./dist/web3.js",

5683
libjsqrc/ethereumjs/dist/web3-light.js

File diff suppressed because it is too large

2
libjsqrc/ethereumjs/dist/web3-light.min.js

File diff suppressed because one or more lines are too long

260
libjsqrc/ethereumjs/dist/web3.js

File diff suppressed because one or more lines are too long

85
libjsqrc/ethereumjs/dist/web3.js.map

File diff suppressed because one or more lines are too long

4
libjsqrc/ethereumjs/dist/web3.min.js

File diff suppressed because one or more lines are too long

153
libjsqrc/ethereumjs/example/coin.html

@ -1,153 +0,0 @@
<!doctype>
<html>
<title>JevCoin</title>
<head>
<script type="text/javascript" src="../dist/web3.js"></script>
</head>
<body>
<h1>JevCoin <code id="contract_addr"></code></h1>
<div>
<strong>Balance</strong>
<span id="balance"></strong>
</div>
<div>
<span>Address:</span>
<input type="text" id="address" style="width:200px">
<span>Amount:</span>
<input type="text" id="amount" style="width:200px">
<button onclick="transact()">Send</button>
<span id="message"></span>
</div>
<hr>
<table width="100%" id="table">
<tr><td style="width:40%;">Address</td><td>Balance</td></tr>
<tbody id="table_body"></tbody>
</table>
</body>
<script type="text/javascript">
var web3 = require('web3');
var eth = web3.eth;
web3.setProvider(new web3.providers.HttpProvider('http://localhost:8080'));
var desc = [{
"name": "balance(address)",
"type": "function",
"inputs": [{
"name": "who",
"type": "address"
}],
"constant": true,
"outputs": [{
"name": "value",
"type": "uint256"
}]
}, {
"name": "send(address,uint256)",
"type": "function",
"inputs": [{
"name": "to",
"type": "address"
}, {
"name": "value",
"type": "uint256"
}],
"outputs": []
}, {
"name":"Changed",
"type":"event",
"inputs": [
{"name":"from","type":"address","indexed":true},
{"name":"amount","type":"uint256","indexed":true},
],
}];
var address = localStorage.getItem("address");
// deploy if not exist
if(address === null) {
var code = "0x60056013565b61014f8061003a6000396000f35b620f42406000600033600160a060020a0316815260200190815260200160002081905550560060e060020a600035048063d0679d3414610020578063e3d670d71461003457005b61002e600435602435610049565b60006000f35b61003f600435610129565b8060005260206000f35b806000600033600160a060020a03168152602001908152602001600020541061007157610076565b610125565b806000600033600160a060020a03168152602001908152602001600020908154039081905550806000600084600160a060020a031681526020019081526020016000209081540190819055508033600160a060020a03167fb52dda022b6c1a1f40905a85f257f689aa5d69d850e49cf939d688fbe5af594660006000a38082600160a060020a03167fb52dda022b6c1a1f40905a85f257f689aa5d69d850e49cf939d688fbe5af594660006000a35b5050565b60006000600083600160a060020a0316815260200190815260200160002054905091905056";
address = web3.eth.transact({from: eth.coinbase, data: code, gas: "1000000"});
localStorage.setItem("address", address);
}
document.querySelector("#contract_addr").innerHTML = address;
var Contract = web3.eth.contract(desc);
contract = new Contract(address);
contract.Changed({from: eth.accounts[0]}).changed(function() {
refresh();
});
function refresh() {
document.querySelector("#balance").innerHTML = contract.balance(eth.coinbase);
var table = document.querySelector("#table_body");
table.innerHTML = ""; // clear
/*var storage = eth.getStorage(address);*/
/*table.innerHTML = "";*/
/*for( var item in storage ) {*/
/*table.innerHTML += "<tr><td>"+item+"</td><td>"+web3.toDecimal(storage[item])+"</td></tr>";*/
/*}*/
}
function transact() {
var to = document.querySelector("#address");
if( to.value.length == 0 ) {
to = "0x4205b06c2cfa0e30359edcab94543266cb6fa1d3";
} else {
if (to.value.substr(0,2) != "0x")
to.value = "0x"+to.value;
}
var value = document.querySelector("#amount");
var amount = parseInt( value.value );
console.log("transact: ", to.value, " => ", amount)
contract.sendTransaction({from: eth.accounts[0]}).send( to.value, amount );
to.value = "";
value.value = "";
var message = document.querySelector("#message")
message.innerHTML = "Submitted";
setTimeout(function() {
message.innerHTML = "";
}, 1000);
}
refresh();
</script>
</html>
<!--
contract JevCoin {
function JevCoin()
{
balances[msg.sender] = 1000000;
}
event Changed(address indexed from, uint indexed amount);
function send(address to, uint value)
{
if( balances[msg.sender] < value ) return;
balances[msg.sender] -= value;
balances[to] += value;
Changed(msg.sender, value);
Changed(to, value);
}
function balance(address who) constant returns(uint t)
{
t = balances[who];
}
mapping(address => uint256) balances;
}
-!>

5
libjsqrc/ethereumjs/example/event_inc.html

@ -25,6 +25,7 @@
var address;
var contract;
var inc;
var update = function (err, x) {
document.getElementById('result').textContent = JSON.stringify(x, null, 2);
@ -55,8 +56,8 @@
}
});
contract.Incremented({odd: true}).watch(update);
inc = contract.Incremented({odd: true});
inc.watch(update);
};
var counter = 0;

2
libjsqrc/ethereumjs/gulpfile.js

@ -73,7 +73,7 @@ gulp.task('buildLight', ['clean'], function () {
.pipe(gulp.dest( DEST ));
});
gulp.task('buildStandalone', [], function () {
gulp.task('buildStandalone', ['clean'], function () {
return browserify(browserifyOptions)
.require('./' + src + '.js', {expose: 'web3'})
.require('bignumber.js') // expose it to dapp users

2
libjsqrc/ethereumjs/lib/utils/config.js

@ -71,7 +71,7 @@ module.exports = {
ETH_SIGNATURE_LENGTH: 4,
ETH_UNITS: ETH_UNITS,
ETH_BIGNUMBER_ROUNDING_MODE: { ROUNDING_MODE: BigNumber.ROUND_DOWN },
ETH_POLLING_TIMEOUT: 1000,
ETH_POLLING_TIMEOUT: 1000/2,
defaultBlock: 'latest',
defaultAccount: undefined
};

2
libjsqrc/ethereumjs/lib/version.json

@ -1,3 +1,3 @@
{
"version": "0.5.0"
"version": "0.6.0"
}

33
libjsqrc/ethereumjs/lib/web3.js

@ -34,7 +34,6 @@ var Filter = require('./web3/filter');
var utils = require('./utils/utils');
var formatters = require('./web3/formatters');
var RequestManager = require('./web3/requestmanager');
var Method = require('./web3/method');
var c = require('./utils/config');
var Property = require('./web3/property');
var Batch = require('./web3/batch');
@ -94,8 +93,7 @@ web3.eth.filter = function (fil, eventParams, options, formatter) {
return fil(eventParams, options);
}
// what outputLogFormatter? that's wrong
//return new Filter(fil, watches.eth(), formatters.outputLogFormatter);
// output logs works for blockFilter and pendingTransaction filters?
return new Filter(fil, watches.eth(), formatter || formatters.outputLogFormatter);
};
/*jshint maxparams:3 */
@ -150,6 +148,23 @@ Object.defineProperty(web3.eth, 'defaultAccount', {
}
});
// EXTEND
web3._extend = function(extension){
/*jshint maxcomplexity: 6 */
if(extension.property && !web3[extension.property])
web3[extension.property] = {};
setupMethods(web3[extension.property] || web3, extension.methods || []);
setupProperties(web3[extension.property] || web3, extension.properties || []);
};
web3._extend.formatters = formatters;
web3._extend.utils = utils;
web3._extend.Method = require('./web3/method');
web3._extend.Property = require('./web3/property');
/// setups all api methods
setupProperties(web3, web3Properties);
setupMethods(web3.net, net.methods);
@ -159,17 +174,5 @@ setupProperties(web3.eth, eth.properties);
setupMethods(web3.db, db.methods);
setupMethods(web3.shh, shh.methods);
web3.admin = {};
web3.admin.setSessionKey = function(s) { web3.admin.sessionKey = s; };
var blockQueueStatus = new Property({
name: 'blockQueueStatus',
call: 'admin_eth_blockQueueStatus',
params: 1,
inputFormatter: [function() { return web3.admin.sessionKey; }]
});
setupMethods(web3.admin, [blockQueueStatus]);
module.exports = web3;

10
libjsqrc/ethereumjs/lib/web3/eth.js

@ -77,11 +77,11 @@ var uncleCountCall = function (args) {
/// @returns an array of objects describing web3.eth api methods
var getBalance = new Method({
name: 'getBalance',
call: 'eth_getBalance',
params: 2,
inputFormatter: [utils.toAddress, formatters.inputDefaultBlockNumberFormatter],
outputFormatter: formatters.outputBigNumberFormatter
name: 'getBalance',
call: 'eth_getBalance',
params: 2,
inputFormatter: [utils.toAddress, formatters.inputDefaultBlockNumberFormatter],
outputFormatter: formatters.outputBigNumberFormatter
});
var getStorageAt = new Method({

99
libjsqrc/ethereumjs/lib/web3/filter.js

@ -74,21 +74,36 @@ var getOptions = function (options) {
};
};
var Filter = function (options, methods, formatter) {
var implementation = {};
methods.forEach(function (method) {
method.attachToObject(implementation);
});
this.options = getOptions(options);
this.implementation = implementation;
this.callbacks = [];
this.formatter = formatter;
this.filterId = this.implementation.newFilter(this.options);
/**
Adds the callback and sets up the methods, to iterate over the results.
@method getLogsAtStart
@param {Object} self
@param {funciton}
*/
var getLogsAtStart = function(self, callback){
// call getFilterLogs for the first watch callback start
if (!utils.isString(self.options)) {
self.get(function (err, messages) {
// don't send all the responses to all the watches again... just to self one
if (err) {
callback(err);
}
messages.forEach(function (message) {
callback(null, message);
});
});
}
};
Filter.prototype.watch = function (callback) {
this.callbacks.push(callback);
var self = this;
/**
Adds the callback and sets up the methods, to iterate over the results.
@method pollFilter
@param {Object} self
*/
var pollFilter = function(self) {
var onMessage = function (error, messages) {
if (error) {
@ -105,29 +120,55 @@ Filter.prototype.watch = function (callback) {
});
};
// call getFilterLogs on start
if (!utils.isString(this.options)) {
this.get(function (err, messages) {
// don't send all the responses to all the watches again... just to this one
if (err) {
callback(err);
}
RequestManager.getInstance().startPolling({
method: self.implementation.poll.call,
params: [self.filterId],
}, self.filterId, onMessage, self.stopWatching.bind(self));
messages.forEach(function (message) {
callback(null, message);
};
var Filter = function (options, methods, formatter) {
var self = this;
var implementation = {};
methods.forEach(function (method) {
method.attachToObject(implementation);
});
this.options = getOptions(options);
this.implementation = implementation;
this.callbacks = [];
this.pollFilters = [];
this.formatter = formatter;
this.implementation.newFilter(this.options, function(error, id){
if(error) {
self.callbacks.forEach(function(callback){
callback(error);
});
});
} else {
self.filterId = id;
// get filter logs at start
self.callbacks.forEach(function(callback){
getLogsAtStart(self, callback);
});
pollFilter(self);
}
});
};
Filter.prototype.watch = function (callback) {
this.callbacks.push(callback);
if(this.filterId) {
getLogsAtStart(this, callback);
pollFilter(this);
}
RequestManager.getInstance().startPolling({
method: this.implementation.poll.call,
params: [this.filterId],
}, this.filterId, onMessage, this.stopWatching.bind(this));
return this;
};
Filter.prototype.stopWatching = function () {
RequestManager.getInstance().stopPolling(this.filterId);
this.implementation.uninstallFilter(this.filterId);
// remove filter async
this.implementation.uninstallFilter(this.filterId, function(){});
this.callbacks = [];
};
@ -149,6 +190,8 @@ Filter.prototype.get = function (callback) {
return self.formatter ? self.formatter(log) : log;
});
}
return this;
};
module.exports = Filter;

22
libjsqrc/ethereumjs/lib/web3/formatters.js

@ -89,8 +89,10 @@ var inputTransactionFormatter = function (options){
* @returns {Object} transaction
*/
var outputTransactionFormatter = function (tx){
tx.blockNumber = utils.toDecimal(tx.blockNumber);
tx.transactionIndex = utils.toDecimal(tx.transactionIndex);
if(tx.blockNumber !== null)
tx.blockNumber = utils.toDecimal(tx.blockNumber);
if(tx.transactionIndex !== null)
tx.transactionIndex = utils.toDecimal(tx.transactionIndex);
tx.nonce = utils.toDecimal(tx.nonce);
tx.gas = utils.toDecimal(tx.gas);
tx.gasPrice = utils.toBigNumber(tx.gasPrice);
@ -112,7 +114,8 @@ var outputBlockFormatter = function(block) {
block.gasUsed = utils.toDecimal(block.gasUsed);
block.size = utils.toDecimal(block.size);
block.timestamp = utils.toDecimal(block.timestamp);
block.number = utils.toDecimal(block.number);
if(block.number !== null)
block.number = utils.toDecimal(block.number);
block.difficulty = utils.toBigNumber(block.difficulty);
block.totalDifficulty = utils.toBigNumber(block.totalDifficulty);
@ -135,13 +138,12 @@ var outputBlockFormatter = function(block) {
* @returns {Object} log
*/
var outputLogFormatter = function(log) {
if (log === null) { // 'pending' && 'latest' filters are nulls
return null;
}
log.blockNumber = utils.toDecimal(log.blockNumber);
log.transactionIndex = utils.toDecimal(log.transactionIndex);
log.logIndex = utils.toDecimal(log.logIndex);
if(log.blockNumber !== null)
log.blockNumber = utils.toDecimal(log.blockNumber);
if(log.transactionIndex !== null)
log.transactionIndex = utils.toDecimal(log.transactionIndex);
if(log.logIndex !== null)
log.logIndex = utils.toDecimal(log.logIndex);
return log;
};

13
libjsqrc/ethereumjs/lib/web3/function.js

@ -23,6 +23,7 @@
var web3 = require('../web3');
var coder = require('../solidity/coder');
var utils = require('../utils/utils');
var formatters = require('./formatters');
var sha3 = require('../utils/sha3');
/**
@ -46,6 +47,12 @@ SolidityFunction.prototype.extractCallback = function (args) {
}
};
SolidityFunction.prototype.extractDefaultBlock = function (args) {
if (args.length > this._inputTypes.length && !utils.isObject(args[args.length -1])) {
return formatters.inputDefaultBlockNumberFormatter(args.pop()); // modify the args array!
}
};
/**
* Should be used to create payload from arguments
*
@ -97,15 +104,17 @@ SolidityFunction.prototype.unpackOutput = function (output) {
SolidityFunction.prototype.call = function () {
var args = Array.prototype.slice.call(arguments).filter(function (a) {return a !== undefined; });
var callback = this.extractCallback(args);
var defaultBlock = this.extractDefaultBlock(args);
var payload = this.toPayload(args);
if (!callback) {
var output = web3.eth.call(payload);
var output = web3.eth.call(payload, defaultBlock);
return this.unpackOutput(output);
}
var self = this;
web3.eth.call(payload, function (error, output) {
web3.eth.call(payload, defaultBlock, function (error, output) {
callback(error, self.unpackOutput(output));
});
};

4
libjsqrc/ethereumjs/lib/web3/httpprovider.js

@ -35,6 +35,7 @@ HttpProvider.prototype.send = function (payload) {
var request = new XMLHttpRequest();
request.open('POST', this.host, false);
request.setRequestHeader('Content-type','application/json');
try {
request.send(JSON.stringify(payload));
@ -78,7 +79,8 @@ HttpProvider.prototype.sendAsync = function (payload, callback) {
};
request.open('POST', this.host, true);
request.setRequestHeader('Content-type','application/json');
try {
request.send(JSON.stringify(payload));
} catch(error) {

1
libjsqrc/ethereumjs/lib/web3/property.js

@ -29,7 +29,6 @@ var Property = function (options) {
this.setter = options.setter;
this.outputFormatter = options.outputFormatter;
this.inputFormatter = options.inputFormatter;
this.params = options.params;
};
/**

59
libjsqrc/ethereumjs/lib/web3/requestmanager.js

@ -43,9 +43,9 @@ var RequestManager = function (provider) {
arguments.callee._singletonInstance = this;
this.provider = provider;
this.polls = [];
this.polls = {};
this.timeout = null;
this.poll();
this.isPolling = false;
};
/**
@ -140,6 +140,11 @@ RequestManager.prototype.sendBatch = function (data, callback) {
*/
RequestManager.prototype.setProvider = function (p) {
this.provider = p;
if (this.provider && !this.isPolling) {
this.poll();
this.isPolling = true;
}
};
/*jshint maxparams:4 */
@ -156,7 +161,7 @@ RequestManager.prototype.setProvider = function (p) {
* @todo cleanup number of params
*/
RequestManager.prototype.startPolling = function (data, pollId, callback, uninstall) {
this.polls.push({data: data, id: pollId, callback: callback, uninstall: uninstall});
this.polls['poll_'+ pollId] = {data: data, id: pollId, callback: callback, uninstall: uninstall};
};
/*jshint maxparams:3 */
@ -167,24 +172,19 @@ RequestManager.prototype.startPolling = function (data, pollId, callback, uninst
* @param {Number} pollId
*/
RequestManager.prototype.stopPolling = function (pollId) {
for (var i = this.polls.length; i--;) {
var poll = this.polls[i];
if (poll.id === pollId) {
this.polls.splice(i, 1);
}
}
delete this.polls['poll_'+ pollId];
};
/**
* Should be called to reset polling mechanism of request manager
* Should be called to reset the polling mechanism of the request manager
*
* @method reset
*/
RequestManager.prototype.reset = function () {
this.polls.forEach(function (poll) {
poll.uninstall(poll.id);
});
this.polls = [];
for (var key in this.polls) {
this.polls[key].uninstall();
}
this.polls = {};
if (this.timeout) {
clearTimeout(this.timeout);
@ -199,9 +199,10 @@ RequestManager.prototype.reset = function () {
* @method poll
*/
RequestManager.prototype.poll = function () {
/*jshint maxcomplexity: 6 */
this.timeout = setTimeout(this.poll.bind(this), c.ETH_POLLING_TIMEOUT);
if (!this.polls.length) {
if (Object.keys(this.polls).length === 0) {
return;
}
@ -210,9 +211,18 @@ RequestManager.prototype.poll = function () {
return;
}
var payload = Jsonrpc.getInstance().toBatchPayload(this.polls.map(function (data) {
return data.data;
}));
var pollsData = [];
var pollsKeys = [];
for (var key in this.polls) {
pollsData.push(this.polls[key].data);
pollsKeys.push(key);
}
if (pollsData.length === 0) {
return;
}
var payload = Jsonrpc.getInstance().toBatchPayload(pollsData);
var self = this;
this.provider.sendAsync(payload, function (error, results) {
@ -220,14 +230,21 @@ RequestManager.prototype.poll = function () {
if (error) {
return;
}
if (!utils.isArray(results)) {
throw errors.InvalidResponse(results);
}
results.map(function (result, index) {
result.callback = self.polls[index].callback;
return result;
var key = pollsKeys[index];
// make sure the filter is still installed after arrival of the request
if (self.polls[key]) {
result.callback = self.polls[key].callback;
return result;
} else
return false;
}).filter(function (result) {
return !!result;
}).filter(function (result) {
var valid = Jsonrpc.getInstance().isValidResponse(result);
if (!valid) {

4
libjsqrc/ethereumjs/lib/web3/watches.js

@ -29,11 +29,11 @@ var eth = function () {
switch(type) {
case 'latest':
args.pop();
args.shift();
this.params = 0;
return 'eth_newBlockFilter';
case 'pending':
args.pop();
args.shift();
this.params = 0;
return 'eth_newPendingTransactionFilter';
default:

2
libjsqrc/ethereumjs/package.js

@ -1,7 +1,7 @@
/* jshint ignore:start */
Package.describe({
name: 'ethereum:web3',
version: '0.5.0',
version: '0.6.0',
summary: 'Ethereum JavaScript API, middleware to talk to a ethreum node over RPC',
git: 'https://github.com/ethereum/ethereum.js',
// By default, Meteor will default to using README.md for documentation.

6
libjsqrc/ethereumjs/package.json

@ -1,7 +1,7 @@
{
"name": "web3",
"namespace": "ethereum",
"version": "0.5.0",
"version": "0.6.0",
"description": "Ethereum JavaScript API, middleware to talk to a ethereum node over RPC",
"main": "./index.js",
"directories": {
@ -17,11 +17,11 @@
},
"devDependencies": {
"bower": ">=1.3.0",
"browserify": ">=6.0",
"browserify": ">=10.0",
"chai": "^2.1.1",
"coveralls": "^2.11.2",
"del": ">=0.1.1",
"exorcist": "^0.1.6",
"exorcist": "^0.4.0",
"gulp": ">=3.4.0",
"gulp-jshint": ">=1.5.0",
"gulp-rename": ">=1.2.0",

55
libjsqrc/ethereumjs/test/contract.js

@ -66,7 +66,7 @@ describe('web3.eth.contract', function () {
provider.injectValidation(function (payload) {
if (step === 0) {
step = 1;
provider.injectResult(3);
provider.injectResult('0x3');
assert.equal(payload.jsonrpc, '2.0');
assert.equal(payload.method, 'eth_newFilter');
assert.deepEqual(payload.params[0], {
@ -105,7 +105,7 @@ describe('web3.eth.contract', function () {
'0000000000000000000000000000000000000000000000000000000000000008'
}]]);
var r = payload.filter(function (p) {
return p.jsonrpc === '2.0' && p.method === 'eth_getFilterChanges' && p.params[0] === 3;
return p.jsonrpc === '2.0' && p.method === 'eth_getFilterChanges' && p.params[0] === '0x3';
});
assert.equal(r.length > 0, true);
}
@ -114,7 +114,8 @@ describe('web3.eth.contract', function () {
var contract = web3.eth.contract(desc).at(address);
var res = 0;
contract.Changed({from: address}).watch(function(err, result) {
var event = contract.Changed({from: address});
event.watch(function(err, result) {
assert.equal(result.args.from, address);
assert.equal(result.args.amount, 1);
assert.equal(result.args.t1, 1);
@ -133,6 +134,7 @@ describe('web3.eth.contract', function () {
provider.injectResult('0x0000000000000000000000000000000000000000000000000000000000000032');
var signature = 'balance(address)'
var address = '0x1234567890123456789012345678901234567890';
provider.injectValidation(function (payload) {
assert.equal(payload.method, 'eth_call');
assert.deepEqual(payload.params, [{
@ -147,6 +149,28 @@ describe('web3.eth.contract', function () {
assert.deepEqual(new BigNumber(0x32), r);
});
it('should call constant function with default block', function () {
var provider = new FakeHttpProvider();
web3.setProvider(provider);
web3.reset();
provider.injectResult('0x0000000000000000000000000000000000000000000000000000000000000032');
var signature = 'balance(address)'
var address = '0x1234567890123456789012345678901234567890';
provider.injectValidation(function (payload) {
assert.equal(payload.method, 'eth_call');
assert.deepEqual(payload.params, [{
data: '0x' + sha3(signature).slice(0, 8) + '0000000000000000000000001234567890123456789012345678901234567890',
to: address
}, '0xb']);
});
var contract = web3.eth.contract(desc).at(address);
var r = contract.balance(address, 11);
assert.deepEqual(new BigNumber(0x32), r);
});
it('should sendTransaction to contract function', function () {
var provider = new FakeHttpProvider();
web3.setProvider(provider);
@ -218,6 +242,31 @@ describe('web3.eth.contract', function () {
});
it('should explicitly make a call with optional params and defaultBlock', function () {
var provider = new FakeHttpProvider();
web3.setProvider(provider);
web3.reset();
provider.injectResult('0x0000000000000000000000000000000000000000000000000000000000000032');
var signature = 'balance(address)';
var address = '0x1234567890123456789012345678901234567890';
provider.injectValidation(function (payload) {
assert.equal(payload.method, 'eth_call');
assert.deepEqual(payload.params, [{
data: '0x' + sha3(signature).slice(0, 8) + '0000000000000000000000001234567890123456789012345678901234567890',
to: address,
from: address,
gas: '0xc350'
}, '0xb']);
});
var contract = web3.eth.contract(desc).at(address);
var r = contract.balance.call(address, {from: address, gas: 50000}, 11);
assert.deepEqual(new BigNumber(0x32), r);
});
it('should sendTransaction with optional params', function () {
var provider = new FakeHttpProvider();
web3.setProvider(provider);

70
libjsqrc/ethereumjs/test/formatters.outputBlockFormatter.js

@ -8,38 +8,72 @@ describe('formatters', function () {
it('should return the correct value', function () {
assert.deepEqual(formatters.outputBlockFormatter({
hash: '0x34234kjh23kj4234',
parentHash: '0x34234kjh23kj4234',
miner: '0x34234kjh23kj4234',
stateRoot: '0x34234kjh23kj4234',
sha3Uncles: '0x34234kjh23kj4234',
bloom: '0x34234kjh23kj4234',
hash: '0xd6960376d6c6dea93647383ffb245cfced97ccc5c7525397a543a72fdaea5265',
parentHash: '0x83ffb245cfced97ccc5c75253d6960376d6c6dea93647397a543a72fdaea5265',
miner: '0xdcc6960376d6c6dea93647383ffb245cfced97cf',
stateRoot: '0x54dda68af07643f68739a6e9612ad157a26ae7e2ce81f77842bb5835fbcde583',
sha3Uncles: '0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347',
bloom: '0xd6960376d6c6dea93647383ffb245cfced97ccc5c7525397a543a72fdaea5265',
difficulty: '0x3e8',
totalDifficulty: '0x3e8',
number: '0x3e8',
gasLimit: '0x3e8',
gasUsed: '0x3e8',
timestamp: '0x3e8',
extraData: '0x34234kjh23kj4234',
nonce: '0x34234kjh23kj4234',
children: ['0x34234kjh23kj4234'],
extraData: '0xd6960376d6c6dea93647383ffb245cfced97ccc5c7525397a543a72fdaea5265',
nonce: '0xd6960376d6c6dea93647383ffb245cfced97ccc5c7525397a543a72fdaea5265',
size: '0x3e8'
}), {
hash: '0x34234kjh23kj4234',
parentHash: '0x34234kjh23kj4234',
miner: '0x34234kjh23kj4234',
stateRoot: '0x34234kjh23kj4234',
sha3Uncles: '0x34234kjh23kj4234',
bloom: '0x34234kjh23kj4234',
hash: '0xd6960376d6c6dea93647383ffb245cfced97ccc5c7525397a543a72fdaea5265',
parentHash: '0x83ffb245cfced97ccc5c75253d6960376d6c6dea93647397a543a72fdaea5265',
miner: '0xdcc6960376d6c6dea93647383ffb245cfced97cf',
stateRoot: '0x54dda68af07643f68739a6e9612ad157a26ae7e2ce81f77842bb5835fbcde583',
sha3Uncles: '0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347',
bloom: '0xd6960376d6c6dea93647383ffb245cfced97ccc5c7525397a543a72fdaea5265',
difficulty: new BigNumber(1000),
totalDifficulty: new BigNumber(1000),
number: 1000,
gasLimit: 1000,
gasUsed: 1000,
timestamp: 1000,
extraData: '0x34234kjh23kj4234',
nonce: '0x34234kjh23kj4234',
children: ['0x34234kjh23kj4234'],
extraData: '0xd6960376d6c6dea93647383ffb245cfced97ccc5c7525397a543a72fdaea5265',
nonce: '0xd6960376d6c6dea93647383ffb245cfced97ccc5c7525397a543a72fdaea5265',
size: 1000
});
});
it('should return the correct value, when null values are present', function () {
assert.deepEqual(formatters.outputBlockFormatter({
hash: null,
parentHash: '0x83ffb245cfced97ccc5c75253d6960376d6c6dea93647397a543a72fdaea5265',
miner: null,
stateRoot: '0x54dda68af07643f68739a6e9612ad157a26ae7e2ce81f77842bb5835fbcde583',
sha3Uncles: '0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347',
bloom: '0xd6960376d6c6dea93647383ffb245cfced97ccc5c7525397a543a72fdaea5265',
difficulty: '0x3e8',
totalDifficulty: '0x3e8',
number: null,
gasLimit: '0x3e8',
gasUsed: '0x3e8',
timestamp: '0x3e8',
extraData: '0xd6960376d6c6dea93647383ffb245cfced97ccc5c7525397a543a72fdaea5265',
nonce: null,
size: '0x3e8'
}), {
hash: null,
parentHash: '0x83ffb245cfced97ccc5c75253d6960376d6c6dea93647397a543a72fdaea5265',
miner: null,
stateRoot: '0x54dda68af07643f68739a6e9612ad157a26ae7e2ce81f77842bb5835fbcde583',
sha3Uncles: '0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347',
bloom: '0xd6960376d6c6dea93647383ffb245cfced97ccc5c7525397a543a72fdaea5265',
difficulty: new BigNumber(1000),
totalDifficulty: new BigNumber(1000),
number: null,
gasLimit: 1000,
gasUsed: 1000,
timestamp: 1000,
extraData: '0xd6960376d6c6dea93647383ffb245cfced97ccc5c7525397a543a72fdaea5265',
nonce: null,
size: 1000
});
});

32
libjsqrc/ethereumjs/test/formatters.outputLogFormatter.js

@ -9,17 +9,37 @@ describe('formatters', function () {
transactionIndex: '0x3e8',
logIndex: '0x3e8',
blockNumber: '0x3e8',
transactionHash: '0x7b2274657374223a2274657374227d',
blockHash: '0x7b2274657374223a2274657374227d',
data: '0x7b2274657374223a2274657374227d',
transactionHash: '0xd6960376d6c6dea93647383ffb245cfced97ccc5c7525397a543a72fdaea5265',
blockHash: '0xd6960376d6c6dea93647383ffb245cfced97ccc5c7525397a543a72fdaea5265',
data: '0x7b2274657374223a2274657374227',
topics: ['0x68656c6c6f','0x6d79746f70696373']
}), {
transactionIndex: 1000,
logIndex: 1000,
blockNumber: 1000,
transactionHash: '0x7b2274657374223a2274657374227d',
blockHash: '0x7b2274657374223a2274657374227d',
data: '0x7b2274657374223a2274657374227d',
transactionHash: '0xd6960376d6c6dea93647383ffb245cfced97ccc5c7525397a543a72fdaea5265',
blockHash: '0xd6960376d6c6dea93647383ffb245cfced97ccc5c7525397a543a72fdaea5265',
data: '0x7b2274657374223a2274657374227',
topics: ['0x68656c6c6f','0x6d79746f70696373']
});
});
it('should return the correct value, when null values are present', function () {
assert.deepEqual(formatters.outputLogFormatter({
transactionIndex: null,
logIndex: null,
blockNumber: null,
transactionHash: null,
blockHash: null,
data: '0x7b2274657374223a2274657374227',
topics: ['0x68656c6c6f','0x6d79746f70696373']
}), {
transactionIndex: null,
logIndex: null,
blockNumber: null,
transactionHash: null,
blockHash: null,
data: '0x7b2274657374223a2274657374227',
topics: ['0x68656c6c6f','0x6d79746f70696373']
});
});

35
libjsqrc/ethereumjs/test/formatters.outputTransactionFormatter.js

@ -7,7 +7,7 @@ describe('formatters', function () {
it('should return the correct value', function () {
assert.deepEqual(formatters.outputTransactionFormatter({
input: '0x34234kjh23kj4234',
input: '0x3454645634534',
from: '0x00000',
to: '0x00000',
value: '0x3e8',
@ -16,9 +16,9 @@ describe('formatters', function () {
nonce: '0xb',
transactionIndex: '0x1',
blockNumber: '0x3e8',
blockHash: '0x34234bf23bf4234'
blockHash: '0xc9b9cdc2092a9d6589d96662b1fd6949611163fb3910cf8a173cd060f17702f9'
}), {
input: '0x34234kjh23kj4234',
input: '0x3454645634534',
from: '0x00000',
to: '0x00000',
value: new BigNumber(1000),
@ -26,9 +26,36 @@ describe('formatters', function () {
gasPrice: new BigNumber(1000),
nonce: 11,
blockNumber: 1000,
blockHash: '0x34234bf23bf4234',
blockHash: '0xc9b9cdc2092a9d6589d96662b1fd6949611163fb3910cf8a173cd060f17702f9',
transactionIndex: 1
});
});
it('should return the correct value, when null values are present', function () {
assert.deepEqual(formatters.outputTransactionFormatter({
input: '0x3454645634534',
from: '0x00000',
to: null,
value: '0x3e8',
gas: '0x3e8',
gasPrice: '0x3e8',
nonce: '0xb',
transactionIndex: null,
blockNumber: null,
blockHash: null
}), {
input: '0x3454645634534',
from: '0x00000',
to: null,
value: new BigNumber(1000),
gas: 1000,
gasPrice: new BigNumber(1000),
nonce: 11,
blockNumber: null,
blockHash: null,
transactionIndex: null
});
});
});
});

10
libjsqrc/ethereumjs/test/helpers/FakeHttpProvider2.js

@ -15,11 +15,21 @@ FakeHttpProvider2.prototype.injectResultList = function (list) {
FakeHttpProvider2.prototype.getResponse = function () {
var result = this.resultList[this.counter];
this.counter++;
// add fallback result value
if(!result)
result = {
result: undefined
};
if (result.type === 'batch') {
this.injectBatchResults(result.result);
} else {
this.injectResult(result.result);
}
this.counter = 0;
return this.response;
};

7
libjsqrc/ethereumjs/test/helpers/FakeXMLHttpRequest.js

@ -6,6 +6,9 @@ var FakeXMLHttpRequest = function () {
this.readyState = 4;
this.onreadystatechange = null;
this.async = false;
this.headers = {
'Content-Type': 'text/plain'
};
};
FakeXMLHttpRequest.prototype.open = function (method, host, async) {
@ -15,6 +18,10 @@ FakeXMLHttpRequest.prototype.open = function (method, host, async) {
this.async = async;
};
FakeXMLHttpRequest.prototype.setRequestHeader = function(name, value) {
this.headers[name] = value;
};
FakeXMLHttpRequest.prototype.send = function (payload) {
assert.equal(typeof payload, 'string');
if (this.async) {

76
libjsqrc/ethereumjs/test/web3.extend.js

@ -0,0 +1,76 @@
var chai = require('chai');
var assert = chai.assert;
var FakeHttpProvider = require('./helpers/FakeHttpProvider');
var web3 = require('../lib/web3');
var tests = [{
properties: [new web3._extend.Property({
name: 'gasPrice',
getter: 'eth_gasPrice',
outputFormatter: web3._extend.formatters.outputBigNumberFormatter
})]
},{
methods: [new web3._extend.Method({
name: 'getBalance',
call: 'eth_getBalance',
params: 2,
inputFormatter: [web3._extend.utils.toAddress, web3._extend.formatters.inputDefaultBlockNumberFormatter],
outputFormatter: web3._extend.formatters.outputBigNumberFormatter
})]
},{
property: 'admin',
properties: [new web3._extend.Property({
name: 'gasPrice',
getter: 'eth_gasPrice',
outputFormatter: web3._extend.formatters.outputBigNumberFormatter
})],
methods: [new web3._extend.Method({
name: 'getBalance',
call: 'eth_getBalance',
params: 2,
inputFormatter: [web3._extend.utils.toAddress, web3._extend.formatters.inputDefaultBlockNumberFormatter],
outputFormatter: web3._extend.formatters.outputBigNumberFormatter
})]
}];
describe('web3', function () {
describe('_extend', function () {
tests.forEach(function (test, index) {
it('test no: ' + index, function () {
web3._extend(test);
if(test.properties)
test.properties.forEach(function(property){
var provider = new FakeHttpProvider();
web3.setProvider(provider);
provider.injectResult('');
provider.injectValidation(function (payload) {
assert.equal(payload.jsonrpc, '2.0');
assert.equal(payload.method, property.getter);
});
if(test.property) {
assert.isObject(web3[test.property][property.name]);
assert.isFunction(web3[test.property]['get'+ property.name.charAt(0).toUpperCase() + property.name.slice(1)]);
} else {
assert.isObject(web3[property.name]);
assert.isFunction(web3['get'+ property.name.charAt(0).toUpperCase() + property.name.slice(1)]);
}
});
if(test.methods)
test.methods.forEach(function(property){
if(test.property)
assert.isFunction(web3[test.property][property.name]);
else
assert.isFunction(web3[property.name]);
});
});
});
});
});

1
libjsqrc/js.qrc

@ -2,6 +2,7 @@
<qresource prefix="/js">
<file>bignumber.min.js</file>
<file>setup.js</file>
<file>admin.js</file>
<file alias="webthree.js">ethereumjs/dist/web3.js</file>
</qresource>
</RCC>

26
libsolidity/ArrayUtils.cpp

@ -39,11 +39,6 @@ void ArrayUtils::copyArrayToStorage(ArrayType const& _targetType, ArrayType cons
// stack layout: [source_ref] [source_byte_off] [source length] target_ref target_byte_off (top)
solAssert(_targetType.location() == DataLocation::Storage, "");
solAssert(
_sourceType.location() == DataLocation::CallData ||
_sourceType.location() == DataLocation::Storage,
"Given array location not implemented."
);
IntegerType uint256(256);
Type const* targetBaseType = _targetType.isByteArray() ? &uint256 : &(*_targetType.getBaseType());
@ -52,6 +47,7 @@ void ArrayUtils::copyArrayToStorage(ArrayType const& _targetType, ArrayType cons
// TODO unroll loop for small sizes
bool sourceIsStorage = _sourceType.location() == DataLocation::Storage;
bool fromCalldata = _sourceType.location() == DataLocation::CallData;
bool directCopy = sourceIsStorage && sourceBaseType->isValueType() && *sourceBaseType == *targetBaseType;
bool haveByteOffsetSource = !directCopy && sourceIsStorage && sourceBaseType->getStorageBytes() <= 16;
bool haveByteOffsetTarget = !directCopy && targetBaseType->getStorageBytes() <= 16;
@ -71,6 +67,13 @@ void ArrayUtils::copyArrayToStorage(ArrayType const& _targetType, ArrayType cons
// retrieve source length
if (_sourceType.location() != DataLocation::CallData || !_sourceType.isDynamicallySized())
retrieveLength(_sourceType); // otherwise, length is already there
if (_sourceType.location() == DataLocation::Memory && _sourceType.isDynamicallySized())
{
// increment source pointer to point to data
m_context << eth::Instruction::SWAP1 << u256(0x20);
m_context << eth::Instruction::ADD << eth::Instruction::SWAP1;
}
// stack: target_ref source_ref source_length
m_context << eth::Instruction::DUP3;
// stack: target_ref source_ref source_length target_ref
@ -164,9 +167,9 @@ void ArrayUtils::copyArrayToStorage(ArrayType const& _targetType, ArrayType cons
StorageItem(m_context, *sourceBaseType).retrieveValue(SourceLocation(), true);
}
else if (sourceBaseType->isValueType())
CompilerUtils(m_context).loadFromMemoryDynamic(*sourceBaseType, true, true, false);
CompilerUtils(m_context).loadFromMemoryDynamic(*sourceBaseType, fromCalldata, true, false);
else
solAssert(false, "Copying of unknown type requested: " + sourceBaseType->toString());
solAssert(false, "Copying of type " + _sourceType.toString(false) + " to storage not yet supported.");
// stack: target_ref target_data_end source_data_pos target_data_pos source_data_end [target_byte_offset] [source_byte_offset] <source_value>...
solAssert(
2 + byteOffsetSize + sourceBaseType->getSizeOnStack() <= 16,
@ -419,6 +422,10 @@ void ArrayUtils::convertLengthToSize(ArrayType const& _arrayType, bool _pad) con
}
else
{
solAssert(
_arrayType.getBaseType()->getCalldataEncodedSize() > 0,
"Copying nested dynamic arrays not yet implemented."
);
if (!_arrayType.isByteArray())
m_context << _arrayType.getBaseType()->getCalldataEncodedSize() << eth::Instruction::MUL;
else if (_pad)
@ -485,6 +492,7 @@ void ArrayUtils::accessIndex(ArrayType const& _arrayType) const
switch (location)
{
case DataLocation::CallData:
case DataLocation::Memory:
if (!_arrayType.isByteArray())
{
m_context << eth::Instruction::SWAP1;
@ -494,7 +502,7 @@ void ArrayUtils::accessIndex(ArrayType const& _arrayType) const
if (_arrayType.getBaseType()->isValueType())
CompilerUtils(m_context).loadFromMemoryDynamic(
*_arrayType.getBaseType(),
true,
location == DataLocation::CallData,
!_arrayType.isByteArray(),
false
);
@ -527,8 +535,6 @@ void ArrayUtils::accessIndex(ArrayType const& _arrayType) const
m_context << eth::Instruction::ADD << u256(0);
}
break;
case DataLocation::Memory:
solAssert(false, "Memory lvalues not yet implemented.");
}
}

15
libsolidity/Compiler.cpp

@ -163,14 +163,14 @@ void Compiler::appendConstructor(FunctionDefinition const& _constructor)
{
CompilerContext::LocationSetter locationSetter(m_context, _constructor);
// copy constructor arguments from code to memory and then to stack, they are supplied after the actual program
unsigned argumentSize = 0;
for (ASTPointer<VariableDeclaration> const& var: _constructor.getParameters())
argumentSize += var->getType()->getCalldataEncodedSize();
if (argumentSize > 0)
if (!_constructor.getParameters().empty())
{
CompilerUtils(m_context).fetchFreeMemoryPointer();
m_context << u256(argumentSize) << eth::Instruction::DUP1;
m_context.appendProgramSize(); // program itself
// CODESIZE is program plus manually added arguments
m_context << eth::Instruction::CODESIZE << eth::Instruction::SUB;
// stack: <memptr> <argument size>
m_context << eth::Instruction::DUP1;
m_context.appendProgramSize();
m_context << eth::Instruction::DUP4 << eth::Instruction::CODECOPY;
m_context << eth::Instruction::ADD;
@ -265,8 +265,9 @@ void Compiler::appendCalldataUnpacker(
{
solAssert(arrayType.location() == DataLocation::Memory, "");
// compute data pointer
m_context << eth::Instruction::DUP1 << eth::Instruction::MLOAD;
//@todo once we support nested arrays, this offset needs to be dynamic.
m_context << eth::Instruction::DUP1 << _startOffset << eth::Instruction::ADD;
m_context << _startOffset << eth::Instruction::ADD;
m_context << eth::Instruction::SWAP1 << u256(0x20) << eth::Instruction::ADD;
}
else

2
libsolidity/CompilerUtils.cpp

@ -135,7 +135,7 @@ void CompilerUtils::storeInMemoryDynamic(Type const& _type, bool _padToWordBound
m_context << u256(0) << u256(identityContractAddress);
//@TODO do not use ::CALL if less than 32 bytes?
//@todo in production, we should not have to pair c_callNewAccountGas.
m_context << u256(eth::c_callGas + 10 + eth::c_callNewAccountGas) << eth::Instruction::GAS;
m_context << u256(eth::c_callGas + 15 + eth::c_callNewAccountGas) << eth::Instruction::GAS;
m_context << eth::Instruction::SUB << eth::Instruction::CALL;
m_context << eth::Instruction::POP; // ignore return value

13
libsolidity/ExpressionCompiler.cpp

@ -457,6 +457,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
strings(),
Location::Bare,
false,
nullptr,
true,
true
),
@ -724,8 +725,8 @@ void ExpressionCompiler::endVisit(MemberAccess const& _memberAccess)
case DataLocation::Storage:
setLValue<StorageArrayLength>(_memberAccess, type);
break;
default:
solAssert(false, "Unsupported array location.");
case DataLocation::Memory:
m_context << eth::Instruction::MLOAD;
break;
}
break;
@ -1004,9 +1005,14 @@ void ExpressionCompiler::appendExternalFunctionCall(
_functionType.getReturnParameterTypes().empty() ?
nullptr :
_functionType.getReturnParameterTypes().front().get();
unsigned retSize = firstReturnType ? firstReturnType->getCalldataEncodedSize() : 0;
unsigned retSize = 0;
if (returnSuccessCondition)
retSize = 0; // return value actually is success condition
else if (firstReturnType)
{
retSize = firstReturnType->getCalldataEncodedSize();
solAssert(retSize > 0, "Unable to return dynamic type from external call.");
}
// Evaluate arguments.
TypePointers argumentTypes;
@ -1123,6 +1129,7 @@ void ExpressionCompiler::appendExternalFunctionCall(
//@todo manually update free memory pointer if we accept returning memory-stored objects
utils().fetchFreeMemoryPointer();
utils().loadFromMemoryDynamic(*firstReturnType, false, true, false);
}
}

40
libsolidity/Types.cpp

@ -822,7 +822,7 @@ string ArrayType::toString(bool _short) const
TypePointer ArrayType::externalType() const
{
if (m_arrayKind != ArrayKind::Ordinary)
return shared_from_this();
return this->copyForLocation(DataLocation::CallData, true);
if (!m_baseType->externalType())
return TypePointer();
if (m_baseType->getCategory() == Category::Array && m_baseType->isDynamicallySized())
@ -903,7 +903,7 @@ MemberList const& ContractType::getMembers() const
for (auto const& it: m_contract.getInterfaceFunctions())
members.push_back(MemberList::Member(
it.second->getDeclaration().getName(),
it.second,
it.second->asMemberFunction(),
&it.second->getDeclaration()
));
m_members.reset(new MemberList(members));
@ -1284,6 +1284,7 @@ MemberList const& FunctionType::getMembers() const
strings(),
Location::SetValue,
false,
nullptr,
m_gasSet,
m_valueSet
)
@ -1300,6 +1301,7 @@ MemberList const& FunctionType::getMembers() const
strings(),
Location::SetGas,
false,
nullptr,
m_gasSet,
m_valueSet
)
@ -1404,11 +1406,45 @@ TypePointer FunctionType::copyAndSetGasOrValue(bool _setGas, bool _setValue) con
m_returnParameterNames,
m_location,
m_arbitraryParameters,
m_declaration,
m_gasSet || _setGas,
m_valueSet || _setValue
);
}
FunctionTypePointer FunctionType::asMemberFunction() const
{
TypePointers parameterTypes;
for (auto const& t: m_parameterTypes)
{
auto refType = dynamic_cast<ReferenceType const*>(t.get());
if (refType && refType->location() == DataLocation::CallData)
parameterTypes.push_back(refType->copyForLocation(DataLocation::Memory, false));
else
parameterTypes.push_back(t);
}
//@todo make this more intelligent once we support destructuring assignments
TypePointers returnParameterTypes;
vector<string> returnParameterNames;
if (!m_returnParameterTypes.empty() && m_returnParameterTypes.front()->getCalldataEncodedSize() > 0)
{
returnParameterTypes.push_back(m_returnParameterTypes.front());
returnParameterNames.push_back(m_returnParameterNames.front());
}
return make_shared<FunctionType>(
parameterTypes,
returnParameterTypes,
m_parameterNames,
returnParameterNames,
m_location,
m_arbitraryParameters,
m_declaration,
m_gasSet,
m_valueSet
);
}
vector<string> const FunctionType::getParameterTypeNames() const
{
vector<string> names;

24
libsolidity/Types.h

@ -669,17 +669,19 @@ public:
strings _returnParameterNames = strings(),
Location _location = Location::Internal,
bool _arbitraryParameters = false,
Declaration const* _declaration = nullptr,
bool _gasSet = false,
bool _valueSet = false
):
m_parameterTypes (_parameterTypes),
m_returnParameterTypes (_returnParameterTypes),
m_parameterNames (_parameterNames),
m_returnParameterNames (_returnParameterNames),
m_location (_location),
m_arbitraryParameters (_arbitraryParameters),
m_gasSet (_gasSet),
m_valueSet (_valueSet)
m_parameterTypes(_parameterTypes),
m_returnParameterTypes(_returnParameterTypes),
m_parameterNames(_parameterNames),
m_returnParameterNames(_returnParameterNames),
m_location(_location),
m_arbitraryParameters(_arbitraryParameters),
m_gasSet(_gasSet),
m_valueSet(_valueSet),
m_declaration(_declaration)
{}
TypePointers const& getParameterTypes() const { return m_parameterTypes; }
@ -733,6 +735,12 @@ public:
/// of the parameters to fals.
TypePointer copyAndSetGasOrValue(bool _setGas, bool _setValue) const;
/// @returns a copy of this function type where all return parameters of dynamic size are
/// removed and the location of reference types is changed from CallData to Memory.
/// This is needed if external functions are called on other contracts, as they cannot return
/// dynamic values.
FunctionTypePointer asMemberFunction() const;
private:
static TypePointers parseElementaryTypeVector(strings const& _types);

BIN
mix/qml/img/edittransaction.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 902 B

BIN
mix/qml/img/edittransaction2.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 756 B

BIN
mix/qml/img/edittransaction2@2x.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
mix/qml/img/edittransaction@2x.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

BIN
mix/qml/img/newblock.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 728 B

BIN
mix/qml/img/newblock@2x.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

55
test/TestHelper.cpp

@ -178,7 +178,7 @@ void ImportTest::importState(json_spirit::mObject& _o, State& _state, stateOptio
{
stateOptions.m_bHasBalance = true;
if (bigint(o["balance"].get_str()) >= c_max256plus1)
TBOOST_THROW_EXCEPTION(ValueTooLarge() << errinfo_comment("State 'balance' is equal or greater than 2**256") );
BOOST_THROW_EXCEPTION(ValueTooLarge() << errinfo_comment("State 'balance' is equal or greater than 2**256") );
balance = toInt(o["balance"]);
}
@ -186,7 +186,7 @@ void ImportTest::importState(json_spirit::mObject& _o, State& _state, stateOptio
{
stateOptions.m_bHasNonce = true;
if (bigint(o["nonce"].get_str()) >= c_max256plus1)
TBOOST_THROW_EXCEPTION(ValueTooLarge() << errinfo_comment("State 'nonce' is equal or greater than 2**256") );
BOOST_THROW_EXCEPTION(ValueTooLarge() << errinfo_comment("State 'nonce' is equal or greater than 2**256") );
nonce = toInt(o["nonce"]);
}
@ -230,7 +230,7 @@ void ImportTest::importState(json_spirit::mObject& _o, State& _state)
{
//check that every parameter was declared in state object
if (!stateOptionMap.second.isAllSet())
TBOOST_THROW_EXCEPTION(MissingFields() << errinfo_comment("Import State: Missing state fields!"));
BOOST_THROW_EXCEPTION(MissingFields() << errinfo_comment("Import State: Missing state fields!"));
}
}
@ -246,13 +246,13 @@ void ImportTest::importTransaction(json_spirit::mObject& _o)
assert(_o.count("data") > 0);
if (bigint(_o["nonce"].get_str()) >= c_max256plus1)
TBOOST_THROW_EXCEPTION(ValueTooLarge() << errinfo_comment("Transaction 'nonce' is equal or greater than 2**256") );
BOOST_THROW_EXCEPTION(ValueTooLarge() << errinfo_comment("Transaction 'nonce' is equal or greater than 2**256") );
if (bigint(_o["gasPrice"].get_str()) >= c_max256plus1)
TBOOST_THROW_EXCEPTION(ValueTooLarge() << errinfo_comment("Transaction 'gasPrice' is equal or greater than 2**256") );
BOOST_THROW_EXCEPTION(ValueTooLarge() << errinfo_comment("Transaction 'gasPrice' is equal or greater than 2**256") );
if (bigint(_o["gasLimit"].get_str()) >= c_max256plus1)
TBOOST_THROW_EXCEPTION(ValueTooLarge() << errinfo_comment("Transaction 'gasLimit' is equal or greater than 2**256") );
BOOST_THROW_EXCEPTION(ValueTooLarge() << errinfo_comment("Transaction 'gasLimit' is equal or greater than 2**256") );
if (bigint(_o["value"].get_str()) >= c_max256plus1)
TBOOST_THROW_EXCEPTION(ValueTooLarge() << errinfo_comment("Transaction 'value' is equal or greater than 2**256") );
BOOST_THROW_EXCEPTION(ValueTooLarge() << errinfo_comment("Transaction 'value' is equal or greater than 2**256") );
m_transaction = _o["to"].get_str().empty() ?
Transaction(toInt(_o["value"]), toInt(_o["gasPrice"]), toInt(_o["gasLimit"]), importData(_o), toInt(_o["nonce"]), Secret(_o["secretKey"].get_str())) :
@ -349,9 +349,9 @@ void ImportTest::exportTest(bytes const& _output, State const& _statePost)
{
std::string warning = "Check State: Error! Unexpected output: " + m_TestObject["out"].get_str() + " Expected: " + m_TestObject["expectOut"].get_str();
if (Options::get().checkState)
BOOST_CHECK_MESSAGE((m_TestObject["out"].get_str() == m_TestObject["expectOut"].get_str()), warning);
{TBOOST_CHECK_MESSAGE((m_TestObject["out"].get_str() == m_TestObject["expectOut"].get_str()), warning);}
else
BOOST_WARN_MESSAGE((m_TestObject["out"].get_str() == m_TestObject["expectOut"].get_str()), warning);
TBOOST_WARN_MESSAGE((m_TestObject["out"].get_str() == m_TestObject["expectOut"].get_str()), warning);
m_TestObject.erase(m_TestObject.find("expectOut"));
}
@ -533,24 +533,25 @@ void checkOutput(bytes const& _output, json_spirit::mObject& _o)
void checkStorage(map<u256, u256> _expectedStore, map<u256, u256> _resultStore, Address _expectedAddr)
{
_expectedAddr = _expectedAddr; //unsed parametr when macro
for (auto&& expectedStorePair : _expectedStore)
{
auto& expectedStoreKey = expectedStorePair.first;
auto resultStoreIt = _resultStore.find(expectedStoreKey);
if (resultStoreIt == _resultStore.end())
BOOST_ERROR(_expectedAddr << ": missing store key " << expectedStoreKey);
{TBOOST_ERROR(_expectedAddr << ": missing store key " << expectedStoreKey);}
else
{
auto& expectedStoreValue = expectedStorePair.second;
auto& resultStoreValue = resultStoreIt->second;
BOOST_CHECK_MESSAGE(expectedStoreValue == resultStoreValue, _expectedAddr << ": store[" << expectedStoreKey << "] = " << resultStoreValue << ", expected " << expectedStoreValue);
TBOOST_CHECK_MESSAGE((expectedStoreValue == resultStoreValue), _expectedAddr << ": store[" << expectedStoreKey << "] = " << resultStoreValue << ", expected " << expectedStoreValue);
}
}
BOOST_CHECK_EQUAL(_resultStore.size(), _expectedStore.size());
TBOOST_CHECK_EQUAL(_resultStore.size(), _expectedStore.size());
for (auto&& resultStorePair: _resultStore)
{
if (!_expectedStore.count(resultStorePair.first))
BOOST_ERROR(_expectedAddr << ": unexpected store key " << resultStorePair.first);
TBOOST_ERROR(_expectedAddr << ": unexpected store key " << resultStorePair.first);
}
}
@ -568,14 +569,14 @@ void checkLog(LogEntries _resultLogs, LogEntries _expectedLogs)
void checkCallCreates(eth::Transactions _resultCallCreates, eth::Transactions _expectedCallCreates)
{
BOOST_REQUIRE_EQUAL(_resultCallCreates.size(), _expectedCallCreates.size());
TBOOST_REQUIRE_EQUAL(_resultCallCreates.size(), _expectedCallCreates.size());
for (size_t i = 0; i < _resultCallCreates.size(); ++i)
{
BOOST_CHECK(_resultCallCreates[i].data() == _expectedCallCreates[i].data());
BOOST_CHECK(_resultCallCreates[i].receiveAddress() == _expectedCallCreates[i].receiveAddress());
BOOST_CHECK(_resultCallCreates[i].gas() == _expectedCallCreates[i].gas());
BOOST_CHECK(_resultCallCreates[i].value() == _expectedCallCreates[i].value());
TBOOST_CHECK((_resultCallCreates[i].data() == _expectedCallCreates[i].data()));
TBOOST_CHECK((_resultCallCreates[i].receiveAddress() == _expectedCallCreates[i].receiveAddress()));
TBOOST_CHECK((_resultCallCreates[i].gas() == _expectedCallCreates[i].gas()));
TBOOST_CHECK((_resultCallCreates[i].value() == _expectedCallCreates[i].value()));
}
}
@ -598,7 +599,7 @@ void userDefinedTest(std::function<void(json_spirit::mValue&, bool)> doTests)
cnote << "Testing user defined test: " << filename;
json_spirit::mValue v;
string s = contentsString(filename);
BOOST_REQUIRE_MESSAGE(s.length() > 0, "Contents of " + filename + " is empty. ");
TBOOST_REQUIRE_MESSAGE((s.length() > 0), "Contents of " + filename + " is empty. ");
json_spirit::read_string(s, v);
json_spirit::mObject oSingleTest;
@ -616,11 +617,11 @@ void userDefinedTest(std::function<void(json_spirit::mValue&, bool)> doTests)
}
catch (Exception const& _e)
{
BOOST_ERROR("Failed Test with Exception: " << diagnostic_information(_e));
TBOOST_ERROR("Failed Test with Exception: " << diagnostic_information(_e));
}
catch (std::exception const& _e)
{
BOOST_ERROR("Failed Test with Exception: " << _e.what());
TBOOST_ERROR("Failed Test with Exception: " << _e.what());
}
}
@ -640,18 +641,18 @@ void executeTests(const string& _name, const string& _testPathAppendix, const bo
json_spirit::mValue v;
boost::filesystem::path p(__FILE__);
string s = asString(dev::contents(_pathToFiller.string() + "/" + _name + "Filler.json"));
BOOST_REQUIRE_MESSAGE(s.length() > 0, "Contents of " + _pathToFiller.string() + "/" + _name + "Filler.json is empty.");
TBOOST_REQUIRE_MESSAGE((s.length() > 0), "Contents of " + _pathToFiller.string() + "/" + _name + "Filler.json is empty.");
json_spirit::read_string(s, v);
doTests(v, true);
writeFile(testPath + "/" + _name + ".json", asBytes(json_spirit::write_string(v, true)));
}
catch (Exception const& _e)
{
BOOST_ERROR("Failed filling test with Exception: " << diagnostic_information(_e));
TBOOST_ERROR("Failed filling test with Exception: " << diagnostic_information(_e));
}
catch (std::exception const& _e)
{
BOOST_ERROR("Failed filling test with Exception: " << _e.what());
TBOOST_ERROR("Failed filling test with Exception: " << _e.what());
}
}
@ -660,18 +661,18 @@ void executeTests(const string& _name, const string& _testPathAppendix, const bo
std::cout << "TEST " << _name << ":\n";
json_spirit::mValue v;
string s = asString(dev::contents(testPath + "/" + _name + ".json"));
BOOST_REQUIRE_MESSAGE(s.length() > 0, "Contents of " + testPath + "/" + _name + ".json is empty. Have you cloned the 'tests' repo branch develop and set ETHEREUM_TEST_PATH to its path?");
TBOOST_REQUIRE_MESSAGE((s.length() > 0), "Contents of " + testPath + "/" + _name + ".json is empty. Have you cloned the 'tests' repo branch develop and set ETHEREUM_TEST_PATH to its path?");
json_spirit::read_string(s, v);
Listener::notifySuiteStarted(_name);
doTests(v, false);
}
catch (Exception const& _e)
{
BOOST_ERROR("Failed test with Exception: " << diagnostic_information(_e));
TBOOST_ERROR("Failed test with Exception: " << diagnostic_information(_e));
}
catch (std::exception const& _e)
{
BOOST_ERROR("Failed test with Exception: " << _e.what());
TBOOST_ERROR("Failed test with Exception: " << _e.what());
}
}

4
test/TestHelper.h

@ -32,21 +32,21 @@
#include <libtestutils/Common.h>
#ifdef NOBOOST
#define TBOOST_THROW_EXCEPTION(arg) throw dev::Exception();
#define TBOOST_REQUIRE(arg) if(arg == false) throw dev::Exception();
#define TBOOST_REQUIRE_EQUAL(arg1, arg2) if(arg1 != arg2) throw dev::Exception();
#define TBOOST_CHECK_EQUAL(arg1, arg2) if(arg1 != arg2) throw dev::Exception();
#define TBOOST_CHECK(arg) if(arg == false) throw dev::Exception();
#define TBOOST_REQUIRE_MESSAGE(arg1, arg2) if(arg1 == false) throw dev::Exception();
#define TBOOST_CHECK_MESSAGE(arg1, arg2) if(arg1 == false) throw dev::Exception();
#define TBOOST_WARN_MESSAGE(arg1, arg2) throw dev::Exception();
#define TBOOST_ERROR(arg) throw dev::Exception();
#else
#define TBOOST_THROW_EXCEPTION(arg) BOOST_THROW_EXCEPTION(arg)
#define TBOOST_REQUIRE(arg) BOOST_REQUIRE(arg)
#define TBOOST_REQUIRE_EQUAL(arg1, arg2) BOOST_REQUIRE_EQUAL(arg1, arg2)
#define TBOOST_CHECK(arg) BOOST_CHECK(arg)
#define TBOOST_CHECK_EQUAL(arg1, arg2) BOOST_CHECK_EQUAL(arg1, arg2)
#define TBOOST_CHECK_MESSAGE(arg1, arg2) BOOST_CHECK_MESSAGE(arg1, arg2)
#define TBOOST_REQUIRE_MESSAGE(arg1, arg2) BOOST_REQUIRE_MESSAGE(arg1, arg2)
#define TBOOST_WARN_MESSAGE(arg1, arg2) BOOST_WARN_MESSAGE(arg1, arg2)
#define TBOOST_ERROR(arg) BOOST_ERROR(arg)
#endif

123
test/fuzzTesting/createRandomTest.cpp

@ -36,8 +36,8 @@ extern std::string const c_testExampleVMTest;
extern std::string const c_testExampleBlockchainTest;
//Main Test functinos
void fillRandomTest(std::function<void(json_spirit::mValue&, bool)> doTests, std::string const& testString);
int checkRandomTest(std::function<void(json_spirit::mValue&, bool)> doTests, json_spirit::mValue& value);
void fillRandomTest(std::function<void(json_spirit::mValue&, bool)> _doTests, std::string const& _testString, bool _debug = false);
int checkRandomTest(std::function<void(json_spirit::mValue&, bool)> _doTests, json_spirit::mValue& _value, bool _debug = false);
//Helper Functions
std::vector<std::string> getTypes();
@ -46,8 +46,12 @@ void parseTestWithTypes(std::string& test);
int main(int argc, char *argv[])
{
std::string testSuite;
std::string testFillString;
json_spirit::mValue testmValue;
bool checktest = false;
bool filldebug = false;
bool debug = false;
bool filltest = false;
for (auto i = 0; i < argc; ++i)
{
auto arg = std::string{argv[i]};
@ -62,7 +66,7 @@ int main(int argc, char *argv[])
testSuite = "";
}
else
if (arg == "-checktest" && i + 1 < argc)
if ((arg == "-checktest" || arg == "-filltest") && i + 1 < argc)
{
std::string s;
for (int j = i+1; j < argc; ++j)
@ -72,9 +76,23 @@ int main(int argc, char *argv[])
std::cout << "Error! Content of argument is empty! (Usage -checktest textstream) \n";
return 1;
}
read_string(s, testmValue);
checktest = true;
if (arg == "-filltest")
{
testFillString = s;
filltest = true;
}
else
{
read_string(s, testmValue);
checktest = true;
}
}
else
if (arg == "--debug")
debug = true;
else
if (arg == "--filldebug")
filldebug = true;
}
if (testSuite == "")
@ -83,45 +101,50 @@ int main(int argc, char *argv[])
return 1;
}
else
if (testSuite == "BlockChainTests")
{
if (checktest)
return checkRandomTest(dev::test::doBlockchainTests, testmValue);
else
fillRandomTest(dev::test::doBlockchainTests, c_testExampleBlockchainTest);
}
else
if (testSuite == "TransactionTests")
{
if (checktest)
return checkRandomTest(dev::test::doTransactionTests, testmValue);
std::cout << "Testing: " << testSuite.substr(0, testSuite.length() - 1) << std::endl;
if (testSuite == "BlockChainTests")
{
if (checktest)
return checkRandomTest(dev::test::doBlockchainTests, testmValue, debug);
else
fillRandomTest(dev::test::doBlockchainTests, (filltest) ? testFillString : c_testExampleBlockchainTest, filldebug);
}
else
fillRandomTest(dev::test::doTransactionTests, c_testExampleTransactionTest);
}
else
if (testSuite == "StateTests")
{
if (checktest)
return checkRandomTest(dev::test::doStateTests, testmValue);
if (testSuite == "TransactionTests")
{
if (checktest)
return checkRandomTest(dev::test::doTransactionTests, testmValue, debug);
else
fillRandomTest(dev::test::doTransactionTests, (filltest) ? testFillString : c_testExampleTransactionTest, filldebug);
}
else
fillRandomTest(dev::test::doStateTests, c_testExampleStateTest);
}
else
if (testSuite == "VMTests")
{
if (checktest)
if (testSuite == "StateTests")
{
dev::eth::VMFactory::setKind(dev::eth::VMKind::JIT);
return checkRandomTest(dev::test::doVMTests, testmValue);
if (checktest)
return checkRandomTest(dev::test::doStateTests, testmValue, debug);
else
fillRandomTest(dev::test::doStateTests, (filltest) ? testFillString : c_testExampleStateTest, filldebug);
}
else
fillRandomTest(dev::test::doVMTests, c_testExampleVMTest);
if (testSuite == "VMTests")
{
if (checktest)
{
dev::eth::VMFactory::setKind(dev::eth::VMKind::JIT);
return checkRandomTest(dev::test::doVMTests, testmValue, debug);
}
else
fillRandomTest(dev::test::doVMTests, (filltest) ? testFillString : c_testExampleVMTest, filldebug);
}
}
return 0;
}
int checkRandomTest(std::function<void(json_spirit::mValue&, bool)> doTests, json_spirit::mValue& value)
int checkRandomTest(std::function<void(json_spirit::mValue&, bool)> _doTests, json_spirit::mValue& _value, bool _debug)
{
bool ret = 0;
try
@ -129,14 +152,20 @@ int checkRandomTest(std::function<void(json_spirit::mValue&, bool)> doTests, jso
//redirect all output to the stream
std::ostringstream strCout;
std::streambuf* oldCoutStreamBuf = std::cout.rdbuf();
std::cout.rdbuf( strCout.rdbuf() );
std::cerr.rdbuf( strCout.rdbuf() );
if (!_debug)
{
std::cout.rdbuf( strCout.rdbuf() );
std::cerr.rdbuf( strCout.rdbuf() );
}
doTests(value, false);
_doTests(_value, false);
//restroe output
std::cout.rdbuf(oldCoutStreamBuf);
std::cerr.rdbuf(oldCoutStreamBuf);
if (!_debug)
{
std::cout.rdbuf(oldCoutStreamBuf);
std::cerr.rdbuf(oldCoutStreamBuf);
}
}
catch (dev::Exception const& _e)
{
@ -151,21 +180,24 @@ int checkRandomTest(std::function<void(json_spirit::mValue&, bool)> doTests, jso
return ret;
}
void fillRandomTest(std::function<void(json_spirit::mValue&, bool)> doTests, std::string const& testString)
void fillRandomTest(std::function<void(json_spirit::mValue&, bool)> _doTests, std::string const& _testString, bool _debug)
{
//redirect all output to the stream
std::ostringstream strCout;
std::streambuf* oldCoutStreamBuf = std::cout.rdbuf();
std::cout.rdbuf( strCout.rdbuf() );
std::cerr.rdbuf( strCout.rdbuf() );
if (!_debug)
{
std::cout.rdbuf( strCout.rdbuf() );
std::cerr.rdbuf( strCout.rdbuf() );
}
json_spirit::mValue v;
try
{
std::string newTest = testString;
std::string newTest = _testString;
parseTestWithTypes(newTest);
json_spirit::read_string(newTest, v);
doTests(v, true);
_doTests(v, true);
}
catch(...)
{
@ -173,8 +205,11 @@ void fillRandomTest(std::function<void(json_spirit::mValue&, bool)> doTests, std
}
//restroe output
std::cout.rdbuf(oldCoutStreamBuf);
std::cerr.rdbuf(oldCoutStreamBuf);
if (!_debug)
{
std::cout.rdbuf(oldCoutStreamBuf);
std::cerr.rdbuf(oldCoutStreamBuf);
}
std::cout << json_spirit::write_string(v, true);
}

40
test/libethereum/StateTestsFiller/stSystemOperationsTestFiller.json

@ -1638,6 +1638,46 @@
}
},
"suicideCoinbase": {
"env" : {
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6",
"currentNumber" : "0",
"currentGasLimit" : "10000000",
"currentDifficulty" : "256",
"currentTimestamp" : 1,
"currentCoinbase" : "095e7baea6a6c7c4c2dfeb977efac326af552d87"
},
"expect" : {
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
"balance" : "1999999999999979496",
"nonce" : "1"
}
},
"pre" : {
"095e7baea6a6c7c4c2dfeb977efac326af552d87" : {
"balance" : "1000000000000000000",
"nonce" : "0",
"code" : "{ (SUICIDE 0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b) }",
"storage": {}
},
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
"balance" : "1000000000000000000",
"nonce" : "0",
"code" : "",
"storage": {}
}
},
"transaction" : {
"nonce" : "0",
"gasPrice" : "1",
"gasLimit" : "1000000",
"to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87",
"value" : "100000",
"secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
"data" : ""
}
},
"suicideCaller": {
"env" : {
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6",

2
test/libethereum/state.cpp

@ -80,7 +80,7 @@ void doStateTests(json_spirit::mValue& v, bool _fillin)
#if ETH_FATDB
importer.exportTest(output, theState);
#else
TBOOST_THROW_EXCEPTION(Exception() << errinfo_comment("You can not fill tests when FATDB is switched off"));
BOOST_THROW_EXCEPTION(Exception() << errinfo_comment("You can not fill tests when FATDB is switched off"));
#endif
}
else

4
test/libethereum/transaction.cpp

@ -50,7 +50,7 @@ void doTransactionTests(json_spirit::mValue& _v, bool _fillin)
{
Transaction txFromFields(rlpStream.out(), CheckTransaction::Everything);
if (!txFromFields.signature().isValid())
TBOOST_THROW_EXCEPTION(Exception() << errinfo_comment("transaction from RLP signature is invalid") );
BOOST_THROW_EXCEPTION(Exception() << errinfo_comment("transaction from RLP signature is invalid") );
o["sender"] = toString(txFromFields.sender());
o["transaction"] = ImportTest::makeAllFieldsHex(tObj);
@ -94,7 +94,7 @@ void doTransactionTests(json_spirit::mValue& _v, bool _fillin)
RLP rlp(stream);
txFromRlp = Transaction(rlp.data(), CheckTransaction::Everything);
if (!txFromRlp.signature().isValid())
TBOOST_THROW_EXCEPTION(Exception() << errinfo_comment("transaction from RLP signature is invalid") );
BOOST_THROW_EXCEPTION(Exception() << errinfo_comment("transaction from RLP signature is invalid") );
}
catch(Exception const& _e)
{

6
test/libevm/vm.cpp

@ -395,9 +395,9 @@ void doVMTests(json_spirit::mValue& v, bool _fillin)
{
std::string warning = "Check State: Error! Unexpected output: " + o["out"].get_str() + " Expected: " + o["expectOut"].get_str();
if (Options::get().checkState)
BOOST_CHECK_MESSAGE((o["out"].get_str() == o["expectOut"].get_str()), warning);
{TBOOST_CHECK_MESSAGE((o["out"].get_str() == o["expectOut"].get_str()), warning);}
else
BOOST_WARN_MESSAGE((o["out"].get_str() == o["expectOut"].get_str()), warning);
TBOOST_WARN_MESSAGE((o["out"].get_str() == o["expectOut"].get_str()), warning);
o.erase(o.find("expectOut"));
}
@ -440,7 +440,7 @@ void doVMTests(json_spirit::mValue& v, bool _fillin)
checkLog(fev.sub.logs, test.sub.logs);
}
else // Exception expected
BOOST_CHECK(vmExceptionOccured);
TBOOST_CHECK(vmExceptionOccured);
}
}
}

162
test/libsolidity/SolidityEndToEndTest.cpp

@ -4355,6 +4355,168 @@ BOOST_AUTO_TEST_CASE(accessor_involving_strings)
BOOST_REQUIRE(callContractFunction("data(uint256,uint256)", x, y) == result);
}
BOOST_AUTO_TEST_CASE(bytes_in_function_calls)
{
char const* sourceCode = R"(
contract Main {
string public s1;
string public s2;
function set(string _s1, uint x, string _s2) returns (uint) {
s1 = _s1;
s2 = _s2;
return x;
}
function setIndirectFromMemory(string _s1, uint x, string _s2) returns (uint) {
return this.set(_s1, x, _s2);
}
function setIndirectFromCalldata(string _s1, uint x, string _s2) external returns (uint) {
return this.set(_s1, x, _s2);
}
}
)";
compileAndRun(sourceCode, 0, "Main");
string s1("abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz");
string s2("ABCDEFGHIJKLMNOPQRSTUVXYZABCDEFGHIJKLMNOPQRSTUVXYZABCDEFGHIJKLMNOPQRSTUVXYZ");
vector<size_t> lengthes{0, 31, 64, 65};
for (auto l1: lengthes)
for (auto l2: lengthes)
{
bytes dyn1 = encodeArgs(u256(l1), s1.substr(0, l1));
bytes dyn2 = encodeArgs(u256(l2), s2.substr(0, l2));
bytes args1 = encodeArgs(u256(0x60), u256(l1), u256(0x60 + dyn1.size())) + dyn1 + dyn2;
BOOST_REQUIRE(
callContractFunction("setIndirectFromMemory(string,uint256,string)", asString(args1)) ==
encodeArgs(u256(l1))
);
BOOST_CHECK(callContractFunction("s1()") == encodeArgs(0x20) + dyn1);
BOOST_CHECK(callContractFunction("s2()") == encodeArgs(0x20) + dyn2);
// swapped
bytes args2 = encodeArgs(u256(0x60), u256(l1), u256(0x60 + dyn2.size())) + dyn2 + dyn1;
BOOST_REQUIRE(
callContractFunction("setIndirectFromCalldata(string,uint256,string)", asString(args2)) ==
encodeArgs(u256(l1))
);
BOOST_CHECK(callContractFunction("s1()") == encodeArgs(0x20) + dyn2);
BOOST_CHECK(callContractFunction("s2()") == encodeArgs(0x20) + dyn1);
}
}
BOOST_AUTO_TEST_CASE(return_bytes_internal)
{
char const* sourceCode = R"(
contract Main {
bytes s1;
function doSet(bytes _s1) returns (bytes _r1) {
s1 = _s1;
_r1 = s1;
}
function set(bytes _s1) external returns (uint _r, bytes _r1) {
_r1 = doSet(_s1);
_r = _r1.length;
}
}
)";
compileAndRun(sourceCode, 0, "Main");
string s1("abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz");
vector<size_t> lengthes{0, 31, 64, 65};
for (auto l1: lengthes)
{
bytes dyn1 = encodeArgs(u256(l1), s1.substr(0, l1));
bytes args1 = encodeArgs(u256(0x20)) + dyn1;
BOOST_REQUIRE(
callContractFunction("set(bytes)", asString(args1)) ==
encodeArgs(u256(l1), u256(0x40)) + dyn1
);
}
}
BOOST_AUTO_TEST_CASE(bytes_index_access_memory)
{
char const* sourceCode = R"(
contract Main {
function f(bytes _s1, uint i1, uint i2, uint i3) returns (byte c1, byte c2, byte c3) {
c1 = _s1[i1];
c2 = intern(_s1, i2);
c3 = internIndirect(_s1)[i3];
}
function intern(bytes _s1, uint i) returns (byte c) {
return _s1[i];
}
function internIndirect(bytes _s1) returns (bytes) {
return _s1;
}
}
)";
compileAndRun(sourceCode, 0, "Main");
string s1("abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz");
bytes dyn1 = encodeArgs(u256(s1.length()), s1);
bytes args1 = encodeArgs(u256(0x80), u256(3), u256(4), u256(5)) + dyn1;
BOOST_REQUIRE(
callContractFunction("f(bytes,uint256,uint256,uint256)", asString(args1)) ==
encodeArgs(string{s1[3]}, string{s1[4]}, string{s1[5]})
);
}
BOOST_AUTO_TEST_CASE(bytes_in_constructors_unpacker)
{
char const* sourceCode = R"(
contract Test {
uint public m_x;
bytes public m_s;
function Test(uint x, bytes s) {
m_x = x;
m_s = s;
}
}
)";
string s1("abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz");
bytes dyn1 = encodeArgs(u256(s1.length()), s1);
u256 x = 7;
bytes args1 = encodeArgs(x, u256(0x40)) + dyn1;
compileAndRun(sourceCode, 0, "Test", args1);
BOOST_REQUIRE(callContractFunction("m_x()") == encodeArgs(x));
BOOST_REQUIRE(callContractFunction("m_s()") == encodeArgs(u256(0x20)) + dyn1);
}
BOOST_AUTO_TEST_CASE(bytes_in_constructors_packer)
{
char const* sourceCode = R"(
contract Base {
uint public m_x;
bytes m_s;
function Base(uint x, bytes s) {
m_x = x;
m_s = s;
}
function part(uint i) returns (byte) {
return m_s[i];
}
}
contract Main is Base {
function Main(bytes s, uint x) Base(x, s){}//f(s)) {}
function f(bytes s) returns (bytes) {
return s;
}
}
contract Creator {
function f(uint x, bytes s) returns (uint r, byte ch) {
var c = new Main(s, x);
r = c.m_x();
ch = c.part(x);
}
}
)";
compileAndRun(sourceCode, 0, "Creator");
string s1("abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz");
bytes dyn1 = encodeArgs(u256(s1.length()), s1);
u256 x = 7;
bytes args1 = encodeArgs(x, u256(0x40)) + dyn1;
BOOST_REQUIRE(
callContractFunction("f(uint256,bytes)", asString(args1)) ==
encodeArgs(x, string{s1[unsigned(x)]})
);
}
BOOST_AUTO_TEST_CASE(storage_array_ref)
{
char const* sourceCode = R"(

13
test/libsolidity/SolidityNameAndTypeResolution.cpp

@ -1987,6 +1987,19 @@ BOOST_AUTO_TEST_CASE(mem_array_assignment_changes_base_type)
BOOST_CHECK_THROW(parseTextAndResolveNames(sourceCode), TypeError);
}
BOOST_AUTO_TEST_CASE(dynamic_return_types_not_possible)
{
char const* sourceCode = R"(
contract C {
function f(uint) returns (string);
function g() {
var x = this.f(2);
}
}
)";
BOOST_CHECK_THROW(parseTextAndResolveNames(sourceCode), TypeError);
}
BOOST_AUTO_TEST_SUITE_END()
}

Loading…
Cancel
Save