Skip to content

Commit

Permalink
Merge branch 'develop' of github.com:/ethereum/ethereumj into develop
Browse files Browse the repository at this point in the history
  • Loading branch information
mkalinin committed Oct 11, 2018
2 parents 1293e3c + c03c4bd commit 526321c
Show file tree
Hide file tree
Showing 4 changed files with 145 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,8 @@ public Invocation parseInvocation(byte[] data) {

/**
* Parses Solidity Event and its data members from transaction receipt LogInfo
* Finds corresponding event by its signature hash and thus is not applicable to
* anonymous events
*/
public Invocation parseEvent(LogInfo eventLog) {
CallTransaction.Function event = getBySignatureHash(eventLog.getTopics().get(0).getData());
Expand All @@ -297,10 +299,19 @@ public Invocation parseEvent(LogInfo eventLog) {
List<Param> unindexed = new ArrayList<>();
for (Param input : event.inputs) {
if (input.indexed) {
indexedArgs.add(input.type.decode(eventLog.getTopics().get(indexedArg++).getData()));
continue;
byte[] topicBytes = eventLog.getTopics().get(indexedArg++).getData();
Object decodedTopic;
if (input.type.isDynamicType()) {
// If arrays (including string and bytes) are used as indexed arguments,
// the Keccak-256 hash of it is stored as topic instead.
decodedTopic = SolidityType.Bytes32Type.decodeBytes32(topicBytes);
} else {
decodedTopic = input.type.decode(topicBytes);
}
indexedArgs.add(decodedTopic);
} else {
unindexed.add(input);
}
unindexed.add(input);
}

Object[] unindexedArgs = event.decode(eventLog.getData(), unindexed.toArray(new Param[unindexed.size()]));
Expand Down
14 changes: 13 additions & 1 deletion ethereumj-core/src/main/java/org/ethereum/solidity/Abi.java
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,19 @@ public List<?> decode(byte[] data, byte[][] topics) {
List<Object> result = new ArrayList<>(inputs.size());

byte[][] argTopics = anonymous ? topics : subarray(topics, 1, topics.length);
List<?> indexed = Param.decodeList(filteredInputs(true), ByteUtil.merge(argTopics));
List<Param> indexedParams = filteredInputs(true);
List<Object> indexed = new ArrayList<>();
for (int i = 0; i < indexedParams.size(); i++) {
Object decodedTopic;
if (indexedParams.get(i).type.isDynamicType()) {
// If arrays (including string and bytes) are used as indexed arguments,
// the Keccak-256 hash of it is stored as topic instead.
decodedTopic = SolidityType.Bytes32Type.decodeBytes32(argTopics[i], 0);
} else {
decodedTopic = indexedParams.get(i).type.decode(argTopics[i]);
}
indexed.add(decodedTopic);
}
List<?> notIndexed = Param.decodeList(filteredInputs(false), data);

for (Param input : inputs) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,11 @@ public byte[] encode(Object value) {

@Override
public Object decode(byte[] encoded, int offset) {
return Arrays.copyOfRange(encoded, offset, offset + getFixedSize());
return decodeBytes32(encoded, offset);
}

public static byte[] decodeBytes32(byte[] encoded, int offset) {
return Arrays.copyOfRange(encoded, offset, offset + 32);
}
}

Expand Down
113 changes: 113 additions & 0 deletions ethereumj-core/src/test/java/org/ethereum/log/DecodeLogTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,14 @@
package org.ethereum.log;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

import org.ethereum.core.CallTransaction;
import org.ethereum.solidity.Abi;
import org.ethereum.util.ByteUtil;
import org.ethereum.vm.DataWord;
import org.ethereum.vm.LogInfo;
import org.junit.Assert;
import org.junit.Test;
Expand All @@ -39,4 +45,111 @@ public void decodeEventWithIndexedParamsTest() {
Assert.assertArrayEquals(Hex.decode("f84e5656d026ba9c321394a59cca7cd8e705f448"), (byte[]) invocation.args[1]);
Assert.assertEquals(new BigInteger("100"), invocation.args[2]);
}

@Test
public void testBytesIndexedParam() {
String abiJson = "[{\n" +
" 'anonymous': false,\n" +
" 'inputs': [\n" +
" {\n" +
" 'indexed': true,\n" +
" 'name': 'from',\n" +
" 'type': 'address'\n" +
" },\n" +
" {\n" +
" 'indexed': true,\n" +
" 'name': 'to',\n" +
" 'type': 'address'\n" +
" },\n" +
" {\n" +
" 'indexed': false,\n" +
" 'name': 'value',\n" +
" 'type': 'uint256'\n" +
" },\n" +
" {\n" +
" 'indexed': true,\n" +
" 'name': 'data',\n" +
" 'type': 'bytes'\n" +
" }\n" +
" ],\n" +
" 'name': 'Transfer',\n" +
" 'type': 'event'\n" +
" }]";
CallTransaction.Contract contract = new CallTransaction.Contract(abiJson.replaceAll("'", "\""));
List<DataWord> topics = new ArrayList<>();
topics.add(DataWord.of("e19260aff97b920c7df27010903aeb9c8d2be5d310a2c67824cf3f15396e4c16"));
topics.add(DataWord.of("000000000000000000000000c9ca2e8db68ffeb21978ea30a0b762f0ad2d445b"));
topics.add(DataWord.of("000000000000000000000000d71ebe710322f0a95504cdd12294f613536204ce"));
topics.add(DataWord.of("c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"));
byte[] data = Hex.decode("00000000000000000000000000000000000000000000000000002d7982473f00");
LogInfo logInfo = new LogInfo(Hex.decode("2Cc114bbE7b551d62B15C465c7bdCccd9125b182"), topics, data);
CallTransaction.Invocation e = contract.parseEvent(logInfo);

Assert.assertEquals(4, e.args.length);
Assert.assertArrayEquals(Hex.decode("c9ca2e8db68ffeb21978ea30a0b762f0ad2d445b"), (byte[]) e.args[0]);
Assert.assertArrayEquals(Hex.decode("d71ebe710322f0a95504cdd12294f613536204ce"), (byte[]) e.args[1]);
Assert.assertEquals(ByteUtil.bytesToBigInteger(Hex.decode("002d7982473f00")), e.args[2]);
Assert.assertArrayEquals(Hex.decode("c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"), (byte[]) e.args[3]);

// No exception - OK

Abi abi = Abi.fromJson(abiJson.replaceAll("'", "\""));
Abi.Event event = abi.findEvent(p -> true);
List<?> args = event.decode(data, topics.stream().map(DataWord::getData).collect(Collectors.toList()).toArray(new byte[0][]));

Assert.assertEquals(4, args.size());
Assert.assertArrayEquals(Hex.decode("c9ca2e8db68ffeb21978ea30a0b762f0ad2d445b"), (byte[]) args.get(0));
Assert.assertArrayEquals(Hex.decode("d71ebe710322f0a95504cdd12294f613536204ce"), (byte[]) args.get(1));
Assert.assertEquals(ByteUtil.bytesToBigInteger(Hex.decode("002d7982473f00")), args.get(2));
Assert.assertArrayEquals(Hex.decode("c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"), (byte[]) args.get(3));

}

@Test
public void testBytesIndexedParamAnonymous() {
String abiJson = "[{\n" +
" 'anonymous': true,\n" +
" 'inputs': [\n" +
" {\n" +
" 'indexed': true,\n" +
" 'name': 'from',\n" +
" 'type': 'address'\n" +
" },\n" +
" {\n" +
" 'indexed': true,\n" +
" 'name': 'to',\n" +
" 'type': 'address'\n" +
" },\n" +
" {\n" +
" 'indexed': false,\n" +
" 'name': 'value',\n" +
" 'type': 'uint256'\n" +
" },\n" +
" {\n" +
" 'indexed': true,\n" +
" 'name': 'data',\n" +
" 'type': 'bytes'\n" +
" }\n" +
" ],\n" +
" 'name': 'Transfer',\n" +
" 'type': 'event'\n" +
" }]";
CallTransaction.Contract contract = new CallTransaction.Contract(abiJson.replaceAll("'", "\""));
List<DataWord> topics = new ArrayList<>();
topics.add(DataWord.of("000000000000000000000000c9ca2e8db68ffeb21978ea30a0b762f0ad2d445b"));
topics.add(DataWord.of("000000000000000000000000d71ebe710322f0a95504cdd12294f613536204ce"));
topics.add(DataWord.of("c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"));
byte[] data = Hex.decode("00000000000000000000000000000000000000000000000000002d7982473f00");

Abi abi = Abi.fromJson(abiJson.replaceAll("'", "\""));
Abi.Event event = abi.findEvent(p -> true);
List<?> args = event.decode(data, topics.stream().map(DataWord::getData).collect(Collectors.toList()).toArray(new byte[0][]));

Assert.assertEquals(4, args.size());
Assert.assertArrayEquals(Hex.decode("c9ca2e8db68ffeb21978ea30a0b762f0ad2d445b"), (byte[]) args.get(0));
Assert.assertArrayEquals(Hex.decode("d71ebe710322f0a95504cdd12294f613536204ce"), (byte[]) args.get(1));
Assert.assertEquals(ByteUtil.bytesToBigInteger(Hex.decode("002d7982473f00")), args.get(2));
Assert.assertArrayEquals(Hex.decode("c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"), (byte[]) args.get(3));

}
}

0 comments on commit 526321c

Please sign in to comment.