Skip to content

Commit 874a00b

Browse files
authored
fix serialize ABIDefinition with fallback failed && support (#302)
fallback/receive functions
1 parent 2fcb24f commit 874a00b

File tree

6 files changed

+155
-18
lines changed

6 files changed

+155
-18
lines changed

sdk-abi/src/main/java/org/fisco/bcos/sdk/abi/wrapper/ABIDefinition.java

+41-9
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package org.fisco.bcos.sdk.abi.wrapper;
22

3+
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
4+
import com.fasterxml.jackson.annotation.JsonProperty;
35
import java.util.ArrayList;
46
import java.util.Arrays;
57
import java.util.List;
@@ -26,16 +28,38 @@
2628
* blockchain state), view (specified to not modify the blockchain state), nonpayable (function does
2729
* not accept Ether - the default) and payable (function accepts Ether). <br>
2830
*/
31+
@JsonIgnoreProperties(ignoreUnknown = true)
2932
public class ABIDefinition {
33+
public static final String CONSTRUCTOR_TYPE = "constructor";
34+
public static final String FUNCTION_TYPE = "function";
35+
public static final String EVENT_TYPE = "event";
36+
public static final String FALLBACK_TYPE = "fallback";
37+
public static final String RECEIVE_TYPE = "receive";
38+
39+
@JsonProperty("name")
3040
private String name;
41+
42+
@JsonProperty("type")
3143
private String type;
44+
45+
@JsonProperty("constant")
3246
private boolean constant;
47+
48+
@JsonProperty("payable")
3349
private boolean payable;
50+
51+
@JsonProperty("anonymous")
3452
private boolean anonymous;
53+
54+
@JsonProperty("stateMutability")
3555
private String stateMutability;
3656

57+
@JsonProperty("inputs")
3758
private List<NamedType> inputs;
59+
60+
@JsonProperty("outputs")
3861
private List<NamedType> outputs;
62+
3963
public static List<String> CONSTANT_KEY = Arrays.asList("view");
4064

4165
public ABIDefinition() {}
@@ -94,14 +118,19 @@ public static ABIDefinition createDefaultConstructorABIDefinition() {
94118
*/
95119
public String getMethodSignatureAsString() {
96120
StringBuilder result = new StringBuilder();
97-
result.append(name);
121+
// Fix: the name field of the fallback is empty
122+
if (name != null) {
123+
result.append(name);
124+
}
98125
result.append("(");
99-
String params =
100-
getInputs()
101-
.stream()
102-
.map(abi -> abi.getTypeAsString())
103-
.collect(Collectors.joining(","));
104-
result.append(params);
126+
if (getInputs() != null) {
127+
String params =
128+
getInputs()
129+
.stream()
130+
.map(abi -> abi.getTypeAsString())
131+
.collect(Collectors.joining(","));
132+
result.append(params);
133+
}
105134
result.append(")");
106135
return result.toString();
107136
}
@@ -113,8 +142,11 @@ public String getMethodSignatureAsString() {
113142
* @return the method id
114143
*/
115144
public String getMethodId(CryptoSuite cryptoSuite) {
116-
FunctionEncoder encoder = new FunctionEncoder(cryptoSuite);
117-
return encoder.buildMethodId(getMethodSignatureAsString());
145+
if (getType().equals(ABIDefinition.FUNCTION_TYPE)) {
146+
FunctionEncoder encoder = new FunctionEncoder(cryptoSuite);
147+
return encoder.buildMethodId(getMethodSignatureAsString());
148+
}
149+
return "";
118150
}
119151

120152
public boolean isConstant() {

sdk-abi/src/main/java/org/fisco/bcos/sdk/abi/wrapper/ABIDefinitionFactory.java

+19-4
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
package org.fisco.bcos.sdk.abi.wrapper;
22

3+
import org.fisco.bcos.sdk.abi.ABICodecException;
34
import org.fisco.bcos.sdk.crypto.CryptoSuite;
45
import org.fisco.bcos.sdk.utils.ObjectMapperFactory;
56
import org.slf4j.Logger;
67
import org.slf4j.LoggerFactory;
78

89
public class ABIDefinitionFactory {
9-
1010
private static final Logger logger = LoggerFactory.getLogger(ABIDefinitionFactory.class);
1111

1212
private CryptoSuite cryptoSuite;
@@ -28,12 +28,27 @@ public ContractABIDefinition loadABI(String abi) {
2828

2929
ContractABIDefinition contractABIDefinition = new ContractABIDefinition(cryptoSuite);
3030
for (ABIDefinition abiDefinition : abiDefinitions) {
31-
if (abiDefinition.getType().equals("constructor")) {
31+
if (abiDefinition.getType().equals(ABIDefinition.CONSTRUCTOR_TYPE)) {
3232
contractABIDefinition.setConstructor(abiDefinition);
33-
} else if (abiDefinition.getType().equals("function")) {
33+
} else if (abiDefinition.getType().equals(ABIDefinition.FUNCTION_TYPE)) {
3434
contractABIDefinition.addFunction(abiDefinition.getName(), abiDefinition);
35-
} else if (abiDefinition.getType().equals("event")) {
35+
} else if (abiDefinition.getType().equals(ABIDefinition.EVENT_TYPE)) {
3636
contractABIDefinition.addEvent(abiDefinition.getName(), abiDefinition);
37+
} else if (abiDefinition.getType().equals(ABIDefinition.FALLBACK_TYPE)) {
38+
if (contractABIDefinition.hasFallbackFunction()) {
39+
throw new ABICodecException("only single fallback is allowed");
40+
}
41+
contractABIDefinition.setFallbackFunction(abiDefinition);
42+
} else if (abiDefinition.getType().equals(ABIDefinition.RECEIVE_TYPE)) {
43+
if (contractABIDefinition.hasReceiveFunction()) {
44+
throw new ABICodecException("only single receive is allowed");
45+
}
46+
if (abiDefinition.getStateMutability().equals("payable") == false
47+
&& abiDefinition.isPayable() == false) {
48+
throw new ABICodecException(
49+
"the statemutability of receive can only be payable");
50+
}
51+
contractABIDefinition.setReceiveFunction(abiDefinition);
3752
} else {
3853
// skip and do nothing
3954
}

sdk-abi/src/main/java/org/fisco/bcos/sdk/abi/wrapper/ContractABIDefinition.java

+26
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ public class ContractABIDefinition {
1818
private Map<String, List<ABIDefinition>> events = new HashMap<>();
1919
// method id => function
2020
private Map<String, ABIDefinition> methodIDToFunctions = new HashMap<>();
21+
private ABIDefinition fallbackFunction;
22+
private ABIDefinition receiveFunction;
2123
// event topic => topic
2224
private Map<String, ABIDefinition> eventTopicToEvents = new HashMap<>();
2325
private CryptoSuite cryptoSuite;
@@ -107,4 +109,28 @@ public ABIDefinition getABIDefinitionByMethodId(String methodId) {
107109
public ABIDefinition getABIDefinitionByEventTopic(String topic) {
108110
return eventTopicToEvents.get(Numeric.prependHexPrefix(topic));
109111
}
112+
113+
public ABIDefinition getFallbackFunction() {
114+
return fallbackFunction;
115+
}
116+
117+
public void setFallbackFunction(ABIDefinition fallbackFunction) {
118+
this.fallbackFunction = fallbackFunction;
119+
}
120+
121+
public boolean hasFallbackFunction() {
122+
return this.fallbackFunction != null;
123+
}
124+
125+
public boolean hasReceiveFunction() {
126+
return this.receiveFunction != null;
127+
}
128+
129+
public ABIDefinition getReceiveFunction() {
130+
return receiveFunction;
131+
}
132+
133+
public void setReceiveFunction(ABIDefinition receiveFunction) {
134+
this.receiveFunction = receiveFunction;
135+
}
110136
}

sdk-abi/src/test/java/org/fisco/bcos/sdk/test/abi/ABICodecTest.java

+61-3
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,24 @@
11
package org.fisco.bcos.sdk.test.abi;
22

3+
import java.io.IOException;
34
import java.math.BigInteger;
45
import java.util.ArrayList;
56
import java.util.List;
7+
import java.util.Map;
8+
9+
import com.fasterxml.jackson.core.JsonProcessingException;
10+
import com.fasterxml.jackson.databind.ObjectMapper;
611
import org.fisco.bcos.sdk.abi.ABICodec;
712
import org.fisco.bcos.sdk.abi.ABICodecException;
813
import org.fisco.bcos.sdk.abi.wrapper.ABICodecObject;
914
import org.fisco.bcos.sdk.abi.wrapper.ABIDefinition;
15+
import org.fisco.bcos.sdk.abi.wrapper.ABIDefinitionFactory;
1016
import org.fisco.bcos.sdk.abi.wrapper.ABIObject;
1117
import org.fisco.bcos.sdk.abi.wrapper.ABIObjectFactory;
1218
import org.fisco.bcos.sdk.abi.wrapper.ContractABIDefinition;
19+
import org.fisco.bcos.sdk.crypto.CryptoSuite;
20+
import org.fisco.bcos.sdk.model.CryptoType;
21+
import org.fisco.bcos.sdk.utils.ObjectMapperFactory;
1322
import org.junit.Assert;
1423
import org.junit.Test;
1524

@@ -227,9 +236,13 @@ public class ABICodecTest {
227236
+ " \"payable\": false,\n"
228237
+ " \"stateMutability\": \"nonpayable\",\n"
229238
+ " \"type\": \"fallback\"\n"
239+
+ " },\n"
240+
+ " {\n"
241+
+ " \"payable\": false,\n"
242+
+ " \"stateMutability\": \"payable\",\n"
243+
+ " \"type\": \"receive\"\n"
230244
+ " }\n"
231245
+ "]";
232-
233246
// int a, Info[] memory b, string memory c
234247
/*
235248
* {
@@ -291,7 +304,40 @@ function test(int a, Info[] memory b, string memory c) public returns(int) {
291304
private String encodedWithMethodId = "0x00a3c75d" + encoded;
292305

293306
@Test
294-
public void testEncodeFromString() {
307+
public void testEncodeFromString() throws IOException {
308+
CryptoSuite cryptoSuite = new CryptoSuite(CryptoType.ECDSA_TYPE);
309+
ABIDefinitionFactory abiDefinitionFactory = new ABIDefinitionFactory(cryptoSuite);
310+
ContractABIDefinition abiDefinition = abiDefinitionFactory.loadABI(abiDesc);
311+
// check the fallback function
312+
Assert.assertTrue(abiDefinition.getFallbackFunction() != null);
313+
// check the content of the fallback function
314+
Assert.assertTrue(abiDefinition.getFallbackFunction().getStateMutability().equals( "nonpayable"));
315+
Assert.assertTrue(abiDefinition.getFallbackFunction().isPayable() == false);
316+
Assert.assertTrue(abiDefinition.getFallbackFunction().getType().equals("fallback"));
317+
318+
// check receive functions
319+
Assert.assertTrue(abiDefinition.getReceiveFunction() != null);
320+
Assert.assertTrue(abiDefinition.getReceiveFunction().getType().equals("receive"));
321+
322+
// check serialization and deserialization
323+
ObjectMapper objectMapper = ObjectMapperFactory.getObjectMapper();
324+
byte[] encodedABIDefinitions = objectMapper.writeValueAsBytes(abiDefinition.getFallbackFunction());
325+
// decode
326+
ABIDefinition decodedABIDefinition = objectMapper.readValue(encodedABIDefinitions, ABIDefinition.class);
327+
Assert.assertTrue(decodedABIDefinition.getStateMutability().equals( "nonpayable"));
328+
Assert.assertTrue(decodedABIDefinition.isPayable() == false);
329+
Assert.assertTrue(decodedABIDefinition.getType().equals("fallback"));
330+
// test encode/decode for all the functions
331+
for(String key : abiDefinition.getFunctions().keySet())
332+
{
333+
List<ABIDefinition> abiDefinitions = abiDefinition.getFunctions().get(key);
334+
for(int i = 0; i < abiDefinitions.size(); i++) {
335+
ABIDefinition functionAbiDefinition = abiDefinitions.get(i);
336+
encodedABIDefinitions = objectMapper.writeValueAsBytes(functionAbiDefinition);
337+
decodedABIDefinition = objectMapper.readValue(encodedABIDefinitions, ABIDefinition.class);
338+
}
339+
}
340+
295341
List<String> args = new ArrayList<String>();
296342
args.add("100");
297343
// [{"name": "Hello world!", "count": 100, "items": [{"a": 1, "b": 2, "c": 3}]}, {"name":
@@ -401,9 +447,21 @@ public void testEncodeByInterface() {
401447
argsObjects.add(a);
402448
try {
403449
String s1 = abiCodec.encodeMethodByInterface("call(uint256[2],uint256[],bytes,address)", argsObjects);
404-
String abi = "[{\"constant\":false,\"inputs\":[{\"name\":\"u1\",\"type\":\"uint256[2]\"},{\"name\":\"u2\",\"type\":\"uint256[]\"},{\"name\":\"b\",\"type\":\"bytes\"},{\"name\":\"a\",\"type\":\"address\"}],\"name\":\"call\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"get\",\"outputs\":[{\"name\":\"u\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"a\",\"type\":\"uint256\"},{\"name\":\"s\",\"type\":\"string\"}],\"name\":\"add\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"u\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"a\",\"type\":\"uint256\"}],\"name\":\"LogAdd1\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"u\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"a\",\"type\":\"uint256\"}],\"name\":\"LogAdd2\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"u\",\"type\":\"uint256\"},{\"indexed\":true,\"name\":\"a\",\"type\":\"uint256\"},{\"indexed\":true,\"name\":\"s\",\"type\":\"string\"}],\"name\":\"LogAdd3\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"a\",\"type\":\"uint256\"}],\"name\":\"LogAdd4\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"a\",\"type\":\"uint256\"}],\"name\":\"LogAdd5\",\"type\":\"event\"}]";
450+
String abi = "[{\"inputs\":[{\"name\":\"u1\",\"type\":\"uint256[2]\"},{\"name\":\"u2\",\"type\":\"uint256[]\"},{\"name\":\"b\",\"type\":\"bytes\"},{\"name\":\"a\",\"type\":\"address\"}],\"name\":\"call\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"get\",\"outputs\":[{\"name\":\"u\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"a\",\"type\":\"uint256\"},{\"name\":\"s\",\"type\":\"string\"}],\"name\":\"add\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"u\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"a\",\"type\":\"uint256\"}],\"name\":\"LogAdd1\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"u\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"a\",\"type\":\"uint256\"}],\"name\":\"LogAdd2\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"u\",\"type\":\"uint256\"},{\"indexed\":true,\"name\":\"a\",\"type\":\"uint256\"},{\"indexed\":true,\"name\":\"s\",\"type\":\"string\"}],\"name\":\"LogAdd3\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"a\",\"type\":\"uint256\"}],\"name\":\"LogAdd4\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"a\",\"type\":\"uint256\"}],\"name\":\"LogAdd5\",\"type\":\"event\"}]";
405451
String s2 = abiCodec.encodeMethod(abi, "call", argsObjects);
406452
Assert.assertEquals(s1, s2);
453+
// test ABIDefinition
454+
// check constant
455+
CryptoSuite cryptoSuite = new CryptoSuite(CryptoType.ECDSA_TYPE);
456+
ABIDefinitionFactory abiDefinitionFactory = new ABIDefinitionFactory(cryptoSuite);
457+
ContractABIDefinition abiDefinition = abiDefinitionFactory.loadABI(abi);
458+
Map<String, List<ABIDefinition>> functions = abiDefinition.getFunctions();
459+
Assert.assertTrue(functions.containsKey("call"));
460+
List<ABIDefinition> callABIDefinition = functions.get("call");
461+
Assert.assertEquals(1, callABIDefinition.size());
462+
Assert.assertTrue(callABIDefinition.get(0).isConstant());
463+
// check without
464+
407465
} catch (ABICodecException e) {
408466
Assert.fail(e.getMessage());
409467
}

sdk-core/src/main/java/org/fisco/bcos/sdk/network/NetworkImp.java

+7-1
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@ public void start() throws NetworkException {
154154
boolean tryEcdsaConnect = false;
155155
CheckCertExistenceResult result = null;
156156
String ecdsaCryptoInfo = configOption.getCryptoMaterialConfig().toString();
157+
String ecdsaErrorMessage = "";
157158
try {
158159
try {
159160
result = checkCertExistence(false);
@@ -186,6 +187,7 @@ public void start() throws NetworkException {
186187
}
187188
// means that all the ECDSA certificates exist
188189
tryEcdsaConnect = true;
190+
ecdsaErrorMessage += e.getMessage();
189191
connManager.stopNetty();
190192
logger.debug(
191193
"start connManager with the ECDSA sslContext failed, try to use SM sslContext, error info: {}",
@@ -197,7 +199,11 @@ public void start() throws NetworkException {
197199
if (!result.isCheckPassed()) {
198200
if (tryEcdsaConnect) {
199201
String errorMessage =
200-
"\n* Try init the sslContext failed.\n\n* If your blockchain channel config is NON-SM, please provide the NON-SM certificates: "
202+
"\n* Try init the NON-SM sslContext failed and the SM certificates are incomplete . error info: \n"
203+
+ ecdsaErrorMessage;
204+
205+
errorMessage +=
206+
"\n* If your blockchain channel config is NON-SM, please provide the NON-SM certificates: "
201207
+ ecdsaCryptoInfo
202208
+ ".\n";
203209
errorMessage +=

sdk-crypto/src/main/java/org/fisco/bcos/sdk/crypto/keystore/KeyTool.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -306,7 +306,7 @@ private static Method getMethod(
306306
try {
307307
return ec5UtilClass.getDeclaredMethod(methodName, parameterTypes);
308308
} catch (NoSuchMethodException e) {
309-
logger.warn("get method for EC5Util failed, method name: {}", methodName);
309+
logger.debug("try to get method for EC5Util failed, method name: {}", methodName);
310310
return null;
311311
}
312312
}

0 commit comments

Comments
 (0)