/*
* Copyright (c) [2016] [ <ether.camp> ]
* This file is part of the ethereumJ library.
*
* The ethereumJ library 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.
*
* The ethereumJ library 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 the ethereumJ library. If not, see <http://www.gnu.org/licenses/>.
*/
package org.ethereum.core;
import static org.ethereum.crypto.HashUtil.sha3;
import org.junit.Assert;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.spongycastle.util.encoders.Hex;
/**
* @author Anton Nashatyrev
*/
public class ABITest {
private static final Logger logger = LoggerFactory.getLogger("test");
@Test
public void testTransactionCreate() {
// demo only
CallTransaction.Function function = CallTransaction.Function.fromJsonInterface(funcJson1);
Transaction ctx = CallTransaction.createCallTransaction(1, 1_000_000_000, 1_000_000_000,
"86e0497e32a8e1d79fe38ab87dc80140df5470d9", 0, function, "1234567890abcdef1234567890abcdef12345678");
ctx.sign(sha3("974f963ee4571e86e5f9bc3b493e453db9c15e5bd19829a4ef9a790de0da0015".getBytes()));
}
static String funcJson1 = "{ \n" +
" 'constant': false, \n" +
" 'inputs': [{'name':'to', 'type':'address'}], \n" +
" 'name': 'delegate', \n" +
" 'outputs': [], \n" +
" 'type': 'function' \n" +
"} \n";
static {funcJson1 = funcJson1.replaceAll("'", "\"");}
@Test
public void testSimple1() {
logger.info("\n{}", funcJson1);
CallTransaction.Function function = CallTransaction.Function.fromJsonInterface(funcJson1);
Assert.assertEquals("5c19a95c0000000000000000000000001234567890abcdef1234567890abcdef12345678",
Hex.toHexString(function.encode("1234567890abcdef1234567890abcdef12345678")));
Assert.assertEquals("5c19a95c0000000000000000000000001234567890abcdef1234567890abcdef12345678",
Hex.toHexString(function.encode("0x1234567890abcdef1234567890abcdef12345678")));
try {
Hex.toHexString(function.encode("0xa1234567890abcdef1234567890abcdef12345678"));
Assert.assertTrue(false);
} catch (Exception e) {}
try {
Hex.toHexString(function.encode("blabla"));
Assert.assertTrue(false);
} catch (Exception e) {}
}
static String funcJson2 = "{\n" +
" 'constant':false, \n" +
" 'inputs':[], \n" +
" 'name':'tst', \n" +
" 'outputs':[], \n" +
" 'type':'function' \n" +
"}";
static {funcJson2 = funcJson2.replaceAll("'", "\"");}
@Test
public void testSimple2() {
logger.info("\n{}", funcJson2);
CallTransaction.Function function = CallTransaction.Function.fromJsonInterface(funcJson2);
Transaction ctx = CallTransaction.createCallTransaction(1, 1_000_000_000, 1_000_000_000,
"86e0497e32a8e1d79fe38ab87dc80140df5470d9", 0, function);
ctx.sign(sha3("974f963ee4571e86e5f9bc3b493e453db9c15e5bd19829a4ef9a790de0da0015".getBytes()));
Assert.assertEquals("91888f2e", Hex.toHexString(ctx.getData()));
}
static String funcJson3 = "{\n" +
" 'constant':false, \n" +
" 'inputs':[ \n" +
" {'name':'i','type':'int'}, \n" +
" {'name':'u','type':'uint'}, \n" +
" {'name':'i8','type':'int8'}, \n" +
" {'name':'b2','type':'bytes2'}, \n" +
" {'name':'b32','type':'bytes32'} \n" +
" ], \n" +
" 'name':'f1', \n" +
" 'outputs':[], \n" +
" 'type':'function' \n" +
"}\n";
static {funcJson3 = funcJson3.replaceAll("'", "\"");}
@Test
public void test3() {
logger.info("\n{}", funcJson3);
CallTransaction.Function function = CallTransaction.Function.fromJsonInterface(funcJson3);
Assert.assertEquals("a4f72f5a" +
"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb2e" +
"00000000000000000000000000000000000000000000000000000000000004d2" +
"000000000000000000000000000000000000000000000000000000000000007b61" +
"000000000000000000000000000000000000000000000000000000000000007468" +
"6520737472696e6700000000000000000000000000000000000000000000",
Hex.toHexString(function.encode(-1234, 1234, 123, "a", "the string")));
}
static String funcJson4 = "{\n" +
" 'constant':false, \n" +
" 'inputs':[{'name':'i','type':'int[3]'}, {'name':'j','type':'int[]'}], \n" +
" 'name':'f2', \n" +
" 'outputs':[], \n" +
" 'type':'function' \n" +
"}\n";
static {funcJson4 = funcJson4.replaceAll("'", "\"");};
@Test
public void test4() {
logger.info("\n{}", funcJson4);
CallTransaction.Function function = CallTransaction.Function.fromJsonInterface(funcJson4);
Assert.assertEquals("d383b9f6" +
"0000000000000000000000000000000000000000000000000000000000000001" +
"0000000000000000000000000000000000000000000000000000000000000002" +
"0000000000000000000000000000000000000000000000000000000000000003",
Hex.toHexString(function.encode(new int[] {1,2,3})));
Assert.assertEquals(
"d383b9f60000000000000000000000000000000000000000000000000000000000000001" +
"0000000000000000000000000000000000000000000000000000000000000002" +
"0000000000000000000000000000000000000000000000000000000000000003" +
"0000000000000000000000000000000000000000000000000000000000000080" +
"0000000000000000000000000000000000000000000000000000000000000002" +
"0000000000000000000000000000000000000000000000000000000000000004" +
"0000000000000000000000000000000000000000000000000000000000000005",
Hex.toHexString(function.encode(new int[]{1, 2, 3}, new int[]{4, 5})));
}
static String funcJson5 = "{\n" +
" 'constant':false, \n" +
" 'inputs':[{'name':'i','type':'int'}, \n" +
" {'name':'s','type':'bytes'}, \n" +
" {'name':'j','type':'int'}], \n" +
" 'name':'f4', \n" +
" 'outputs':[], \n" +
" 'type':'function' \n" +
"}\n";
static {funcJson5 = funcJson5.replaceAll("'", "\"");};
@Test
public void test5() {
logger.info("\n{}", funcJson5);
CallTransaction.Function function = CallTransaction.Function.fromJsonInterface(funcJson5);
Assert.assertEquals(
"3ed2792b000000000000000000000000000000000000000000000000000000000000006f" +
"0000000000000000000000000000000000000000000000000000000000000060" +
"00000000000000000000000000000000000000000000000000000000000000de" +
"0000000000000000000000000000000000000000000000000000000000000003" +
"abcdef0000000000000000000000000000000000000000000000000000000000",
Hex.toHexString(function.encode(111, new byte[] {(byte) 0xab, (byte) 0xcd, (byte) 0xef}, 222)));
}
@Test
public void decodeDynamicTest1() {
String funcJson = "{\n" +
" 'constant':false, \n" +
" 'inputs':[{'name':'i','type':'int'}, \n" +
" {'name':'s','type':'bytes'}, \n" +
" {'name':'j','type':'int'}], \n" +
" 'name':'f4', \n" +
" 'outputs':[{'name':'i','type':'int'}, \n" +
" {'name':'s','type':'bytes'}, \n" +
" {'name':'j','type':'int'}], \n" +
" 'type':'function' \n" +
"}\n";
funcJson = funcJson.replaceAll("'", "\"");
CallTransaction.Function function = CallTransaction.Function.fromJsonInterface(funcJson);
byte[] bytes = new byte[]{(byte) 0xab, (byte) 0xcd, (byte) 0xef};
byte[] encoded = function.encodeArguments(111, bytes, 222);
Object[] objects = function.decodeResult(encoded);
// System.out.println(Arrays.toString(objects));
Assert.assertEquals(((Number) objects[0]).intValue(), 111);
Assert.assertArrayEquals((byte[]) objects[1], bytes);
Assert.assertEquals(((Number) objects[2]).intValue(), 222);
}
@Test
public void decodeDynamicTest2() {
String funcJson = "{\n" +
" 'constant':false, \n" +
" 'inputs':[{'name':'i','type':'int'}, \n" +
" {'name':'s','type':'string[]'}, \n" +
" {'name':'j','type':'int'}], \n" +
" 'name':'f4', \n" +
" 'outputs':[{'name':'i','type':'int'}, \n" +
" {'name':'s','type':'string[]'}, \n" +
" {'name':'j','type':'int'}], \n" +
" 'type':'function' \n" +
"}\n";
funcJson = funcJson.replaceAll("'", "\"");
CallTransaction.Function function = CallTransaction.Function.fromJsonInterface(funcJson);
String[] strings = new String[] {"aaa", "long string: 123456789012345678901234567890", "ccc"};
byte[] encoded = function.encodeArguments(111, strings, 222);
Object[] objects = function.decodeResult(encoded);
// System.out.println(Arrays.toString(objects));
Assert.assertEquals(((Number) objects[0]).intValue(), 111);
Assert.assertArrayEquals((Object[]) objects[1], strings);
Assert.assertEquals(((Number) objects[2]).intValue(), 222);
}
@Test
public void decodeWithUnknownPropertiesTest() {
String funcJson = "{\n" +
" 'constant':false, \n" +
" 'inputs':[{'name':'i','type':'int'}, \n" +
" {'name':'s','type':'string[]'}, \n" +
" {'name':'j','type':'int'}], \n" +
" 'name':'f4', \n" +
" 'outputs':[{'name':'i','type':'int'}, \n" +
" {'name':'s','type':'string[]'}, \n" +
" {'name':'j','type':'int'}], \n" +
" 'type':'function', \n" +
" 'test':'test' \n" +
"}\n";
funcJson = funcJson.replaceAll("'", "\"");
CallTransaction.Function function = CallTransaction.Function.fromJsonInterface(funcJson);
String[] strings = new String[] {"aaa", "long string: 123456789012345678901234567890", "ccc"};
byte[] encoded = function.encodeArguments(111, strings, 222);
Object[] objects = function.decodeResult(encoded);
Assert.assertEquals(((Number) objects[0]).intValue(), 111);
Assert.assertArrayEquals((Object[]) objects[1], strings);
Assert.assertEquals(((Number) objects[2]).intValue(), 222);
}
@Test
public void decodeWithPayablePropertyTest() {
String funcJson = "{\n" +
" 'constant':false, \n" +
" 'inputs':[{'name':'i','type':'int'}, \n" +
" {'name':'s','type':'string[]'}, \n" +
" {'name':'j','type':'int'}], \n" +
" 'name':'f4', \n" +
" 'outputs':[{'name':'i','type':'int'}, \n" +
" {'name':'s','type':'string[]'}, \n" +
" {'name':'j','type':'int'}], \n" +
" 'type':'function', \n" +
" 'payable':true \n" +
"}\n";
funcJson = funcJson.replaceAll("'", "\"");
CallTransaction.Function function = CallTransaction.Function.fromJsonInterface(funcJson);
Assert.assertTrue(function.payable);
String[] strings = new String[] {"aaa", "long string: 123456789012345678901234567890", "ccc"};
byte[] encoded = function.encodeArguments(111, strings, 222);
Object[] objects = function.decodeResult(encoded);
Assert.assertEquals(((Number) objects[0]).intValue(), 111);
Assert.assertArrayEquals((Object[]) objects[1], strings);
Assert.assertEquals(((Number) objects[2]).intValue(), 222);
}
@Test
public void decodeWithFunctionTypeFallbackTest() {
String funcJson = "{\n" +
" 'constant':false, \n" +
" 'inputs':[{'name':'i','type':'int'}, \n" +
" {'name':'s','type':'string[]'}, \n" +
" {'name':'j','type':'int'}], \n" +
" 'name':'f4', \n" +
" 'outputs':[{'name':'i','type':'int'}, \n" +
" {'name':'s','type':'string[]'}, \n" +
" {'name':'j','type':'int'}], \n" +
" 'type':'fallback' \n" +
"}\n";
funcJson = funcJson.replaceAll("'", "\"");
CallTransaction.Function function = CallTransaction.Function.fromJsonInterface(funcJson);
Assert.assertEquals(CallTransaction.FunctionType.fallback, function.type);
String[] strings = new String[] {"aaa", "long string: 123456789012345678901234567890", "ccc"};
byte[] encoded = function.encodeArguments(111, strings, 222);
Object[] objects = function.decodeResult(encoded);
Assert.assertEquals(((Number) objects[0]).intValue(), 111);
Assert.assertArrayEquals((Object[]) objects[1], strings);
Assert.assertEquals(((Number) objects[2]).intValue(), 222);
}
@Test
public void decodeWithUnknownFunctionTypeTest() {
String funcJson = "{\n" +
" 'constant':false, \n" +
" 'inputs':[{'name':'i','type':'int'}, \n" +
" {'name':'s','type':'string[]'}, \n" +
" {'name':'j','type':'int'}], \n" +
" 'name':'f4', \n" +
" 'outputs':[{'name':'i','type':'int'}, \n" +
" {'name':'s','type':'string[]'}, \n" +
" {'name':'j','type':'int'}], \n" +
" 'type':'test' \n" +
"}\n";
funcJson = funcJson.replaceAll("'", "\"");
CallTransaction.Function function = CallTransaction.Function.fromJsonInterface(funcJson);
Assert.assertEquals(null, function.type);
String[] strings = new String[] {"aaa", "long string: 123456789012345678901234567890", "ccc"};
byte[] encoded = function.encodeArguments(111, strings, 222);
Object[] objects = function.decodeResult(encoded);
Assert.assertEquals(((Number) objects[0]).intValue(), 111);
Assert.assertArrayEquals((Object[]) objects[1], strings);
Assert.assertEquals(((Number) objects[2]).intValue(), 222);
}
}