Skip to content

Commit

Permalink
<feat>(contract): add merge abi logic, support merge 'as' and 'from' …
Browse files Browse the repository at this point in the history
…import, add event sample contracts. (#855)
  • Loading branch information
kyonRay authored Aug 19, 2024
1 parent d3565ba commit 0a86152
Show file tree
Hide file tree
Showing 6 changed files with 145 additions and 15 deletions.
5 changes: 4 additions & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@ jobs:
- run:
name: Setup dependencies
command: |
yum install -y epel-release centos-release-scl which python python-devel
cd /etc/yum.repos.d/
sed -i 's/mirrorlist/#mirrorlist/g' /etc/yum.repos.d/CentOS-*
sed -i 's|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g' /etc/yum.repos.d/CentOS-*
yum update -y
yum install -y git openssl-devel openssl java java-devel
- checkout
- run:
Expand Down
11 changes: 10 additions & 1 deletion src/main/java/console/common/ConsoleUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -1058,6 +1058,15 @@ public static void main(String[] args) {
}

public static Version convertStringToVersion(String version) {
return Version.valueOf("V" + version.replace('.', '_'));
try {
return Version.valueOf("V" + version.replace('.', '_'));
} catch (Exception e) {
System.out.println(
"Invalid solidity version: "
+ version
+ ", only support: "
+ Arrays.toString(Version.values()));
throw e;
}
}
}
17 changes: 11 additions & 6 deletions src/main/java/console/contract/ConsoleContractImpl.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package console.contract;

import static console.contract.utils.ContractCompiler.mergeAbi;
import static console.contract.utils.ContractCompiler.mergeSource;
import static org.fisco.solc.compiler.SolidityCompiler.Options.ABI;
import static org.fisco.solc.compiler.SolidityCompiler.Options.BIN;
import static org.fisco.solc.compiler.SolidityCompiler.Options.METADATA;
Expand Down Expand Up @@ -30,6 +32,7 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Base64;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
Expand Down Expand Up @@ -1073,27 +1076,30 @@ private String getSolidityAbi(String contractFileName) throws Exception {
if (!solFile.exists()) {
throw new Exception("The contract file " + contractFilePath + " doesn't exist!");
}
String contractName = solFile.getName().split("\\.")[0];

List<SolidityCompiler.Option> defaultOptions = Arrays.asList(ABI, BIN, METADATA);
List<SolidityCompiler.Option> options = new ArrayList<>(defaultOptions);

logger.debug(
"compileSolToBinAndAbi, solc version:{} ,basePath: {}",
Version.V0_8_11,
Version.V0_8_26,
solFile.getParentFile().getCanonicalPath());
SolidityCompiler.Option basePath =
new SolidityCompiler.CustomOption(
"base-path", solFile.getParentFile().getCanonicalPath());
options.add(basePath);
String fileName = solFile.getName();
String dir = solFile.getParentFile().getCanonicalPath() + File.separator;

String mergedSource = mergeSource(dir, fileName, new HashSet<>());

// compile ecdsa
SolidityCompiler.Result res =
SolidityCompiler.compile(
solFile,
mergedSource.getBytes(StandardCharsets.UTF_8),
(client.getCryptoType() == CryptoType.SM_TYPE),
true,
Version.V0_8_11,
Version.V0_8_26,
options.toArray(new SolidityCompiler.Option[0]));

if (logger.isDebugEnabled()) {
Expand All @@ -1111,8 +1117,7 @@ private String getSolidityAbi(String contractFileName) throws Exception {
}

CompilationResult result = CompilationResult.parse(res.getOutput());
CompilationResult.ContractMetadata contractMetadata = result.getContract(contractName);
return contractMetadata.abi;
return mergeAbi(result);
}

private String getWasmAbi(String groupId, String pwd, String contractFileName)
Expand Down
56 changes: 49 additions & 7 deletions src/main/java/console/contract/utils/ContractCompiler.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@
import static org.fisco.solc.compiler.SolidityCompiler.Options.METADATA;
import static org.fisco.solc.compiler.SolidityCompiler.Options.USERDOC;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectReader;
import com.fasterxml.jackson.databind.node.ArrayNode;
import console.common.ConsoleUtils;
import console.contract.exceptions.CompileContractException;
import console.contract.model.AbiAndBin;
Expand All @@ -38,6 +42,7 @@
import org.apache.commons.io.FileUtils;
import org.fisco.bcos.codegen.v3.exceptions.CodeGenException;
import org.fisco.bcos.codegen.v3.utils.CodeGenUtils;
import org.fisco.bcos.sdk.v3.utils.ObjectMapperFactory;
import org.fisco.bcos.sdk.v3.utils.StringUtils;
import org.fisco.evm.analysis.EvmAnalyser;
import org.fisco.solc.compiler.CompilationResult;
Expand Down Expand Up @@ -241,7 +246,8 @@ public static AbiAndBin compileSolToBinAndAbi(

String bin = sm ? "" : meta.bin;
String smBin = sm ? meta.bin : "";
AbiAndBin abiAndBin = new AbiAndBin(meta.abi, bin, smBin, meta.devdoc);
String abi = mergeAbi(result);
AbiAndBin abiAndBin = new AbiAndBin(abi, bin, smBin, meta.devdoc);

// evm static analysis
File abiFile = new File(abiDir + contractName + ".abi");
Expand All @@ -268,8 +274,11 @@ public static AbiAndBin compileSolToBinAndAbi(
}
}

String abi = FileUtils.readFileToString(abiFile, StandardCharsets.UTF_8);
abiAndBin.setAbi(abi);
// write abi and re-read abi for add evm analysis result
if (isContractParallelAnalysis) {
abi = FileUtils.readFileToString(abiFile, StandardCharsets.UTF_8);
abiAndBin.setAbi(abi);
}
checkBinaryCode(contractName, meta.bin);
return abiAndBin;
}
Expand All @@ -287,7 +296,10 @@ public static String mergeSource(String currentDir, String sourceFile, Set<Strin
throw new IOException("Source file:" + fullPath + " not found");
}

Pattern pattern = Pattern.compile("^\\s*import\\s+[\"'](.+)[\"']\\s*;\\s*$");
Pattern simpleImport = Pattern.compile("^\\s*import\\s+[\"'](.+)[\"']\\s*;\\s*$");
Pattern asImport = Pattern.compile("^\\s*import\\s+[\"'](.+)[\"']\\s*as\\s*(.+);\\s*$");
Pattern fromImport =
Pattern.compile("^\\s*import\\s+[\\w{}]*\\s+from\\s+['\"](.+)['\"];\\s*$");
try (Scanner scanner = new Scanner(sourceResource, "UTF-8")) {
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
Expand All @@ -305,9 +317,21 @@ public static String mergeSource(String currentDir, String sourceFile, Set<Strin
continue;
}

Matcher matcher = pattern.matcher(line);
if (matcher.find()) {
String depSourcePath = matcher.group(1);
Matcher simpleMatcher = simpleImport.matcher(line);
Matcher fromMatcher = fromImport.matcher(line);
Matcher asMatcher = asImport.matcher(line);
boolean simpleFlag = simpleMatcher.find();
boolean fromFlag = fromMatcher.find();
boolean asFlag = asMatcher.find();
if (simpleFlag || fromFlag || asFlag) {
String depSourcePath;
if (simpleFlag) {
depSourcePath = simpleMatcher.group(1);
} else if (fromFlag) {
depSourcePath = fromMatcher.group(1);
} else {
depSourcePath = asMatcher.group(1);
}
String nextPath = dir + depSourcePath;
if (nextPath.contains("./")) {
nextPath = new File(nextPath).getCanonicalPath();
Expand All @@ -326,6 +350,24 @@ public static String mergeSource(String currentDir, String sourceFile, Set<Strin
return sourceBuffer.toString();
}

public static String mergeAbi(CompilationResult result) throws JsonProcessingException {

List<String> contractNames = result.getContractKeys();
if (contractNames.isEmpty()) {
return null;
}
ObjectReader objectReader = ObjectMapperFactory.getObjectReader();
ArrayNode mainNode = (ArrayNode) objectReader.createArrayNode();
for (String contractName : contractNames) {
String key = contractName.substring(contractName.lastIndexOf(':') + 1);
JsonNode jsonNode = objectReader.readTree(result.getContract(key).abi);
if (jsonNode.isArray() && !jsonNode.isEmpty()) {
mainNode.addAll((ArrayNode) jsonNode);
}
}
return mainNode.toString();
}

public static void checkBinaryCode(String contractName, String binary)
throws CompileContractException {
String externalLibSplitter = "_";
Expand Down
20 changes: 20 additions & 0 deletions src/main/resources/contract/solidity/BaseEvent.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// SPDX-License-Identifier: Apache-2.0
pragma solidity >=0.6.10 <=0.8.26;

contract BaseEvent {

//---------------------------------------------------------------------------------------------------------------
event Transfer(string indexed from_account, string indexed to_account, uint256 indexed amount);
event TransferAccount(string indexed from_account,string indexed to_account);
event TransferAmount(uint256 indexed amount);

function transfer(string memory from_account, string memory to_account, uint256 amount) public {

emit Transfer(from_account, to_account, amount);

emit TransferAccount(from_account, to_account);

emit TransferAmount(amount);

}
}
51 changes: 51 additions & 0 deletions src/main/resources/contract/solidity/EchoEvent.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// SPDX-License-Identifier: Apache-2.0
pragma solidity >=0.6.10 <=0.8.26;

contract BaseEvent {

//---------------------------------------------------------------------------------------------------------------
event Transfer(string indexed from_account, string indexed to_account, uint256 indexed amount);
event TransferAccount(string indexed from_account,string indexed to_account);
event TransferAmount(uint256 indexed amount);

function transfer(string memory from_account, string memory to_account, uint256 amount) public {

emit Transfer(from_account, to_account, amount);

emit TransferAccount(from_account, to_account);

emit TransferAmount(amount);

}
}

contract EchoEvent {

event Echo1(uint256 indexed u);
event Echo2(int256 indexed i);
event Echo3(string indexed s);
event Echo4(uint256 indexed u, int256 indexed i, string indexed s);

function echo(uint256 u, int256 i, string memory s) public returns(uint256, int256, string memory) {

emit Echo1(u);
emit Echo2(i);
emit Echo3(s);
emit Echo4(u, i ,s);

return (u, i , s);
}

event Echo5(bytes32 indexed bsn);
event Echo6(bytes indexed bs);
event Echo7(bytes32 indexed bsn, bytes indexed bs);

function echo(bytes32 bsn, bytes memory bs) public returns(bytes32, bytes memory) {

emit Echo5(bsn);
emit Echo6(bs);
emit Echo7(bsn, bs);

return (bsn, bs);
}
}

0 comments on commit 0a86152

Please sign in to comment.