From 2994eb4e630c2498c2aff272965fbc0a215cf055 Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Thu, 29 Jan 2015 15:26:42 +0100 Subject: Squashed 'libjsqrc/ethereumjs/' changes from 6d59047..94e0e5a 94e0e5a Merge branch 'cpp' into cpp2 8613382 moved comment df17c33 event example c8ee08c contract.js simplified 842b8cf event.js e1c0862 Fix for API. 61e8ae2 events init 2544d2c tests for abi.filters ea7c2fc abi function type 63d9c07 fixed incoming messages 1345a8c log error on console, if api returns an error 83fad0f removed fromFixed, toFixed && offset from tests c2cb2be removed web3.eth.account, fixed #37 09f6335 fixed #23 42a25f2 evaluating solidity method input params git-subtree-dir: libjsqrc/ethereumjs git-subtree-split: 94e0e5ab7d8ec9adcd03fedc3abe5cf6444a5123 --- abi.filters.js | 49 ++++++++++++++ abi.parsers.js | 37 +++++++++++ eth.contract.js | 201 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ eth.methods.js | 1 - event.js | 22 +++++++ web3.methods.js | 3 - 6 files changed, 309 insertions(+), 4 deletions(-) create mode 100644 abi.filters.js create mode 100644 eth.contract.js create mode 100644 event.js diff --git a/abi.filters.js b/abi.filters.js new file mode 100644 index 00000000..42385fd2 --- /dev/null +++ b/abi.filters.js @@ -0,0 +1,49 @@ +var assert = require('assert'); +var abi = require('../lib/abi.js'); + +describe('abi', function() { + it('should filter functions and events from input array properly', function () { + + // given + var description = [{ + "name": "test", + "type": "function", + "inputs": [{ + "name": "a", + "type": "uint256" + } + ], + "outputs": [ + { + "name": "d", + "type": "uint256" + } + ], + }, { + "name": "test2", + "type": "event", + "inputs": [{ + "name": "a", + "type": "uint256" + } + ], + "outputs": [ + { + "name": "d", + "type": "uint256" + } + ] + }]; + + // when + var events = abi.filterEvents(description); + var functions = abi.filterFunctions(description); + + // then + assert.equal(events.length, 1); + assert.equal(events[0].name, 'test2'); + assert.equal(functions.length, 1); + assert.equal(functions[0].name, 'test'); + + }); +}); diff --git a/abi.parsers.js b/abi.parsers.js index 19fa1d4c..12bccf5a 100644 --- a/abi.parsers.js +++ b/abi.parsers.js @@ -5,6 +5,7 @@ var clone = function (object) { return JSON.parse(JSON.stringify(object)); }; var description = [{ "name": "test", + "type": "function", "inputs": [{ "name": "a", "type": "uint256" @@ -339,10 +340,12 @@ describe('abi', function() { // given var d = [{ name: "test", + type: "function", inputs: [{ type: "int" }], outputs: [{ type: "int" }] },{ name: "test2", + type: "function", inputs: [{ type: "string" }], outputs: [{ type: "string" }] }]; @@ -775,10 +778,12 @@ describe('abi', function() { // given var d = [{ name: "test", + type: "function", inputs: [{ type: "int" }], outputs: [{ type: "int" }] },{ name: "test2", + type: "function", inputs: [{ type: "string" }], outputs: [{ type: "string" }] }]; @@ -823,6 +828,38 @@ describe('abi', function() { }); + it('should parse 0x value', function () { + + // given + var d = clone(description); + d[0].outputs = [ + { type: 'int' } + ]; + + // when + var parser = abi.outputParser(d); + + // then + assert.equal(parser.test("0x")[0], 0); + + }); + + it('should parse 0x value', function () { + + // given + var d = clone(description); + d[0].outputs = [ + { type: 'uint' } + ]; + + // when + var parser = abi.outputParser(d); + + // then + assert.equal(parser.test("0x")[0], 0); + + }); + }); }); diff --git a/eth.contract.js b/eth.contract.js new file mode 100644 index 00000000..1a92ec88 --- /dev/null +++ b/eth.contract.js @@ -0,0 +1,201 @@ +var assert = require('assert'); +var contract = require('../lib/contract.js'); + +describe('contract', function() { + it('should create simple contract with one method from abi with explicit type name', function () { + + // given + var description = [{ + "name": "test(uint256)", + "type": "function", + "inputs": [{ + "name": "a", + "type": "uint256" + } + ], + "outputs": [ + { + "name": "d", + "type": "uint256" + } + ] + }]; + + // when + var con = contract(null, description); + + // then + assert.equal('function', typeof con.test); + assert.equal('function', typeof con.test['uint256']); + }); + + it('should create simple contract with one method from abi with implicit type name', function () { + + // given + var description = [{ + "name": "test", + "type": "function", + "inputs": [{ + "name": "a", + "type": "uint256" + } + ], + "outputs": [ + { + "name": "d", + "type": "uint256" + } + ] + }]; + + // when + var con = contract(null, description); + + // then + assert.equal('function', typeof con.test); + assert.equal('function', typeof con.test['uint256']); + }); + + it('should create contract with multiple methods', function () { + + // given + var description = [{ + "name": "test", + "type": "function", + "inputs": [{ + "name": "a", + "type": "uint256" + } + ], + "outputs": [ + { + "name": "d", + "type": "uint256" + } + ], + }, { + "name": "test2", + "type": "function", + "inputs": [{ + "name": "a", + "type": "uint256" + } + ], + "outputs": [ + { + "name": "d", + "type": "uint256" + } + ] + }]; + + // when + var con = contract(null, description); + + // then + assert.equal('function', typeof con.test); + assert.equal('function', typeof con.test['uint256']); + assert.equal('function', typeof con.test2); + assert.equal('function', typeof con.test2['uint256']); + }); + + it('should create contract with overloaded methods', function () { + + // given + var description = [{ + "name": "test", + "type": "function", + "inputs": [{ + "name": "a", + "type": "uint256" + } + ], + "outputs": [ + { + "name": "d", + "type": "uint256" + } + ], + }, { + "name": "test", + "type": "function", + "inputs": [{ + "name": "a", + "type": "string" + } + ], + "outputs": [ + { + "name": "d", + "type": "uint256" + } + ] + }]; + + // when + var con = contract(null, description); + + // then + assert.equal('function', typeof con.test); + assert.equal('function', typeof con.test['uint256']); + assert.equal('function', typeof con.test['string']); + }); + + it('should create contract with no methods', function () { + + // given + var description = [{ + "name": "test(uint256)", + "inputs": [{ + "name": "a", + "type": "uint256" + } + ], + "outputs": [ + { + "name": "d", + "type": "uint256" + } + ] + }]; + + + // when + var con = contract(null, description); + + // then + assert.equal('undefined', typeof con.test); + + }); + + it('should create contract with one event', function () { + + // given + var description = [{ + "name": "test", + "type": "event", + "inputs": [{ + "name": "a", + "type": "uint256" + } + ], + "outputs": [ + { + "name": "d", + "type": "uint256" + } + ] + }]; + + + // when + var con = contract(null, description); + + // then + assert.equal('function', typeof con.test); + assert.equal('function', typeof con.test['uint256']); + + }); + +}); + diff --git a/eth.methods.js b/eth.methods.js index 00226856..7a031c4c 100644 --- a/eth.methods.js +++ b/eth.methods.js @@ -24,7 +24,6 @@ describe('web3', function() { u.propertyExists(web3.eth, 'listening'); u.propertyExists(web3.eth, 'mining'); u.propertyExists(web3.eth, 'gasPrice'); - u.propertyExists(web3.eth, 'account'); u.propertyExists(web3.eth, 'accounts'); u.propertyExists(web3.eth, 'peerCount'); u.propertyExists(web3.eth, 'defaultBlock'); diff --git a/event.js b/event.js new file mode 100644 index 00000000..781f42e5 --- /dev/null +++ b/event.js @@ -0,0 +1,22 @@ +var assert = require('assert'); +var event = require('../lib/event.js'); + +describe('event', function () { + it('should create filter input object from given', function () { + + // given + var address = '0x012345'; + var signature = '0x987654'; + + // when + var impl = event(address, signature); + var result = impl(); + + // then + assert.equal(result.address, address); + assert.equal(result.topics.length, 1); + assert.equal(result.topics[0], signature); + + }); +}); + diff --git a/web3.methods.js b/web3.methods.js index 1b579211..d08495dd 100644 --- a/web3.methods.js +++ b/web3.methods.js @@ -6,8 +6,5 @@ describe('web3', function() { u.methodExists(web3, 'sha3'); u.methodExists(web3, 'toAscii'); u.methodExists(web3, 'fromAscii'); - u.methodExists(web3, 'toFixed'); - u.methodExists(web3, 'fromFixed'); - u.methodExists(web3, 'offset'); }); -- cgit v1.2.3 From a86a3a245219cc3d9c4e5fc146afd61f3f3e7b97 Mon Sep 17 00:00:00 2001 From: Christian Date: Thu, 29 Jan 2015 14:35:28 +0100 Subject: Parsing of events. --- SolidityNameAndTypeResolution.cpp | 43 +++++++++++++++++++++++++++++++++++++++ SolidityParser.cpp | 27 ++++++++++++++++++++++++ 2 files changed, 70 insertions(+) diff --git a/SolidityNameAndTypeResolution.cpp b/SolidityNameAndTypeResolution.cpp index 07f2d638..88f76124 100644 --- a/SolidityNameAndTypeResolution.cpp +++ b/SolidityNameAndTypeResolution.cpp @@ -680,6 +680,49 @@ BOOST_AUTO_TEST_CASE(private_state_variable) BOOST_CHECK_MESSAGE(function == nullptr, "Accessor function of a private variable should not exist"); } +BOOST_AUTO_TEST_CASE(event) +{ + char const* text = R"( + contract c { + event e(uint indexed a, string3 indexed s, bool indexed b); + function f() { e(2, "abc", true); } + })"; + BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text)); +} + +BOOST_AUTO_TEST_CASE(event_too_many_indexed) +{ + char const* text = R"( + contract c { + event e(uint indexed a, string3 indexed b, bool indexed c, uint indexed d); + function f() { e(2, "abc", true); } + })"; + BOOST_CHECK_THROW(parseTextAndResolveNames(text), TypeError); +} + +BOOST_AUTO_TEST_CASE(event_call) +{ + char const* text = R"( + contract c { + event e(uint a, string3 indexed s, bool indexed b); + function f() { e(2, "abc", true); } + })"; + BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text)); +} + +BOOST_AUTO_TEST_CASE(event_inheritance) +{ + char const* text = R"( + contract base { + event e(uint a, string3 indexed s, bool indexed b); + } + contract c is base { + function f() { e(2, "abc", true); } + })"; + BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text)); +} + + BOOST_AUTO_TEST_SUITE_END() } diff --git a/SolidityParser.cpp b/SolidityParser.cpp index 7bfb4c0c..745df98d 100644 --- a/SolidityParser.cpp +++ b/SolidityParser.cpp @@ -586,6 +586,33 @@ BOOST_AUTO_TEST_CASE(modifier_invocation) BOOST_CHECK_NO_THROW(parseText(text)); } +BOOST_AUTO_TEST_CASE(event) +{ + char const* text = R"( + contract c { + event e(); + })"; + BOOST_CHECK_NO_THROW(parseText(text)); +} + +BOOST_AUTO_TEST_CASE(event_arguments) +{ + char const* text = R"( + contract c { + event e(uint a, string32 s); + })"; + BOOST_CHECK_NO_THROW(parseText(text)); +} + +BOOST_AUTO_TEST_CASE(event_arguments_indexed) +{ + char const* text = R"( + contract c { + event e(uint a, string32 indexed s, bool indexed b); + })"; + BOOST_CHECK_NO_THROW(parseText(text)); +} + BOOST_AUTO_TEST_SUITE_END() } -- cgit v1.2.3 From 99a8f58ee3091ef0ff2389f0b7ad8f1e1fe2df01 Mon Sep 17 00:00:00 2001 From: Christian Date: Thu, 29 Jan 2015 16:42:59 +0100 Subject: Code generation for events. --- SolidityEndToEndTest.cpp | 51 ++++++++++++++++++++++++++++++++++++++++++++ solidityExecutionFramework.h | 1 - 2 files changed, 51 insertions(+), 1 deletion(-) diff --git a/SolidityEndToEndTest.cpp b/SolidityEndToEndTest.cpp index f2976707..0df2d914 100644 --- a/SolidityEndToEndTest.cpp +++ b/SolidityEndToEndTest.cpp @@ -1955,6 +1955,57 @@ BOOST_AUTO_TEST_CASE(super_in_constructor) BOOST_CHECK(callContractFunction("f()") == encodeArgs(1 | 2 | 4 | 8)); } +BOOST_AUTO_TEST_CASE(event) +{ + char const* sourceCode = R"( + contract ClientReceipt { + event Deposit(address indexed _from, hash indexed _id, uint _value); + function deposit(hash _id, bool _manually) { + if (_manually) { + hash s = 0x50cb9fe53daa9737b786ab3646f04d0150dc50ef4e75f59509d83667ad5adb20; + log3(msg.value, s, hash(msg.sender), _id); + } else + Deposit(msg.sender, _id, msg.value); + } + } + )"; + compileAndRun(sourceCode); + u256 value(18); + u256 id(0x1234); + for (bool manually: {true, false}) + { + callContractFunctionWithValue("deposit(hash256,bool)", value, id, manually); + BOOST_REQUIRE_EQUAL(m_logs.size(), 1); + BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress); + BOOST_CHECK_EQUAL(h256(m_logs[0].data), h256(u256(value))); + BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 3); + BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::sha3(string("Deposit(address,hash256,uint256)"))); + BOOST_CHECK_EQUAL(m_logs[0].topics[1], h256(m_sender)); + BOOST_CHECK_EQUAL(m_logs[0].topics[2], h256(id)); + } +} + +BOOST_AUTO_TEST_CASE(event_lots_of_data) +{ + char const* sourceCode = R"( + contract ClientReceipt { + event Deposit(address _from, hash _id, uint _value, bool _flag); + function deposit(hash _id) { + Deposit(msg.sender, _id, msg.value, true); + } + } + )"; + compileAndRun(sourceCode); + u256 value(18); + u256 id(0x1234); + callContractFunctionWithValue("deposit(hash256)", value, id); + BOOST_REQUIRE_EQUAL(m_logs.size(), 1); + BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress); + BOOST_CHECK(m_logs[0].data == encodeArgs(m_sender, id, value, true)); + BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 1); + BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::sha3(string("Deposit(address,hash256,uint256,bool)"))); +} + BOOST_AUTO_TEST_SUITE_END() } diff --git a/solidityExecutionFramework.h b/solidityExecutionFramework.h index 7dad9ad4..5a693536 100644 --- a/solidityExecutionFramework.h +++ b/solidityExecutionFramework.h @@ -67,7 +67,6 @@ public: bytes const& callContractFunctionWithValue(std::string _sig, u256 const& _value, Args const&... _arguments) { - FixedHash<4> hash(dev::sha3(_sig)); sendMessage(hash.asBytes() + encodeArgs(_arguments...), false, _value); return m_output; -- cgit v1.2.3 From dbfd0c601913eabc32aa8b937d654d6217300597 Mon Sep 17 00:00:00 2001 From: Christian Date: Thu, 29 Jan 2015 20:02:23 +0100 Subject: Padding fixes. --- SolidityEndToEndTest.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/SolidityEndToEndTest.cpp b/SolidityEndToEndTest.cpp index 0df2d914..b51492e3 100644 --- a/SolidityEndToEndTest.cpp +++ b/SolidityEndToEndTest.cpp @@ -1963,9 +1963,9 @@ BOOST_AUTO_TEST_CASE(event) function deposit(hash _id, bool _manually) { if (_manually) { hash s = 0x50cb9fe53daa9737b786ab3646f04d0150dc50ef4e75f59509d83667ad5adb20; - log3(msg.value, s, hash(msg.sender), _id); + log3(msg.value, s, hash32(msg.sender), _id); } else - Deposit(msg.sender, _id, msg.value); + Deposit(hash32(msg.sender), _id, msg.value); } } )"; @@ -1991,7 +1991,7 @@ BOOST_AUTO_TEST_CASE(event_lots_of_data) contract ClientReceipt { event Deposit(address _from, hash _id, uint _value, bool _flag); function deposit(hash _id) { - Deposit(msg.sender, _id, msg.value, true); + Deposit(msg.sender, hash32(_id), msg.value, true); } } )"; -- cgit v1.2.3