diff --git a/source/contract/contract-maven-plugin/pom.xml b/source/contract/contract-maven-plugin/pom.xml index 7ba6a4f4..63f0e64c 100644 --- a/source/contract/contract-maven-plugin/pom.xml +++ b/source/contract/contract-maven-plugin/pom.xml @@ -103,27 +103,27 @@ maven-plugin-plugin 3.5 - - - org.apache.maven.plugins - maven-compiler-plugin - - 1.8 - 1.8 - UTF-8 - false - true - false - false - - - - org.apache.maven.plugins - maven-surefire-plugin - - true - - - - + + + diff --git a/source/contract/contract-maven-plugin/src/main/java/com/jd/blockchain/ContractCheckMojo.java b/source/contract/contract-maven-plugin/src/main/java/com/jd/blockchain/ContractCheckMojo.java index 1403e079..a57357e0 100644 --- a/source/contract/contract-maven-plugin/src/main/java/com/jd/blockchain/ContractCheckMojo.java +++ b/source/contract/contract-maven-plugin/src/main/java/com/jd/blockchain/ContractCheckMojo.java @@ -1,6 +1,5 @@ package com.jd.blockchain; -import com.jd.blockchain.ledger.BlockchainKeyGenerator; import org.apache.commons.io.FileUtils; import org.apache.maven.model.Model; import org.apache.maven.model.Plugin; @@ -8,6 +7,7 @@ import org.apache.maven.model.PluginExecution; import org.apache.maven.model.io.xpp3.MavenXpp3Reader; import org.apache.maven.model.io.xpp3.MavenXpp3Writer; import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.plugins.annotations.Mojo; import org.apache.maven.plugins.annotations.Parameter; import org.apache.maven.project.MavenProject; @@ -22,11 +22,12 @@ import java.util.Collections; import java.util.List; -@Mojo(name = "Contract.Check") +@Mojo(name = "contractCheck") public class ContractCheckMojo extends AbstractMojo { + Logger LOG = LoggerFactory.getLogger(ContractCheckMojo.class); - public static final String CONTRACT_VERIFY = "Contract.Verify"; + public static final String CONTRACT_VERIFY = "contractVerify"; private static final String CONTRACT_MAVEN_PLUGIN = "contract-maven-plugin"; @@ -36,11 +37,11 @@ public class ContractCheckMojo extends AbstractMojo { private static final String APACHE_MAVEN_PLUGINS = "org.apache.maven.plugins"; - private static final String GOALS_VERIFY = "verify"; + private static final String GOALS_VERIFY = "package"; private static final String GOALS_PACKAGE = "package"; - private static final String OUT_POM_XML = "OutPom.xml"; + private static final String OUT_POM_XML = "ContractPom.xml"; @Parameter(defaultValue = "${project}", required = true, readonly = true) private MavenProject project; @@ -51,7 +52,6 @@ public class ContractCheckMojo extends AbstractMojo { @Parameter private String finalName; - /** * mainClass; */ @@ -73,11 +73,11 @@ public class ContractCheckMojo extends AbstractMojo { * first compile the class, then parse it; */ @Override - public void execute() { + public void execute() throws MojoFailureException { compileFiles(); } - private void compileFiles(){ + private void compileFiles() throws MojoFailureException { try (FileInputStream fis = new FileInputStream(project.getFile())) { MavenXpp3Reader reader = new MavenXpp3Reader(); @@ -107,7 +107,7 @@ public class ContractCheckMojo extends AbstractMojo { } catch (Exception e) { LOG.error(e.getMessage()); - throw new IllegalStateException(e); + throw new MojoFailureException(e.getMessage()); } } @@ -185,7 +185,7 @@ public class ContractCheckMojo extends AbstractMojo { PluginExecution pluginExecution = new PluginExecution(); pluginExecution.setId(id); pluginExecution.setPhase(phase); - List goals = new ArrayList<>(); + List goals = new ArrayList<>(); goals.add(goal); pluginExecution.setGoals(goals); List pluginExecutions = new ArrayList<>(); diff --git a/source/contract/contract-maven-plugin/src/main/java/com/jd/blockchain/ContractVerifyMojo.java b/source/contract/contract-maven-plugin/src/main/java/com/jd/blockchain/ContractVerifyMojo.java index 28d5a1fb..950eb9bc 100644 --- a/source/contract/contract-maven-plugin/src/main/java/com/jd/blockchain/ContractVerifyMojo.java +++ b/source/contract/contract-maven-plugin/src/main/java/com/jd/blockchain/ContractVerifyMojo.java @@ -3,37 +3,25 @@ package com.jd.blockchain; import com.github.javaparser.JavaParser; import com.github.javaparser.ast.CompilationUnit; import com.github.javaparser.ast.ImportDeclaration; -import com.github.javaparser.ast.NodeList; -import com.github.javaparser.ast.PackageDeclaration; -import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration; -import com.github.javaparser.ast.body.MethodDeclaration; import com.github.javaparser.ast.visitor.VoidVisitorAdapter; import com.jd.blockchain.contract.ContractType; -import com.jd.blockchain.utils.IllegalDataException; -import org.apache.commons.codec.digest.DigestUtils; import org.apache.commons.io.FileUtils; -import org.apache.commons.io.IOUtils; import org.apache.maven.plugin.AbstractMojo; -import org.apache.maven.plugin.MojoFailureException; +import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugins.annotations.Mojo; import org.apache.maven.plugins.annotations.Parameter; import org.apache.maven.project.MavenProject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.util.ResourceUtils; import java.io.*; import java.net.URL; import java.net.URLClassLoader; import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Path; import java.util.*; import java.util.jar.Attributes; import java.util.jar.JarEntry; import java.util.jar.JarFile; -import java.util.jar.JarOutputStream; -import java.util.stream.Collectors; import static com.jd.blockchain.ContractCheckMojo.CONTRACT_VERIFY; import static com.jd.blockchain.utils.decompiler.utils.DecompilerUtils.decompileJarFile; @@ -78,12 +66,15 @@ public class ContractVerifyMojo extends AbstractMojo { private static final String BLACK_NAME_LIST = "black.name.list"; @Override - public void execute() throws MojoFailureException { + public void execute() throws MojoExecutionException { try { File jarFile = copyAndManage(); + // 首先校验MainClass + verifyMainClass(jarFile); + Properties config = loadConfig(); List blackNameList = blackNameList(config); @@ -193,23 +184,25 @@ public class ContractVerifyMojo extends AbstractMojo { if (!isOK) { throw new IllegalStateException("There are many Illegal information, please check !!!"); } - - // 加载main-class,开始校验类型 - URL jarURL = jarFile.toURI().toURL(); - ClassLoader classLoader = new URLClassLoader(new URL[]{jarURL}, this.getClass().getClassLoader()); - Attributes m = new JarFile(jarFile).getManifest().getMainAttributes(); - String contractMainClass = m.getValue(Attributes.Name.MAIN_CLASS); - Class mainClass = classLoader.loadClass(contractMainClass); - ContractType.resolve(mainClass); } else { throw new IllegalStateException("There is none class !!!"); } } catch (Exception e) { LOG.error(e.getMessage()); - throw new MojoFailureException(e.getMessage()); + throw new MojoExecutionException(e.getMessage()); } } + private void verifyMainClass(File jarFile) throws Exception { + // 加载main-class,开始校验类型 + URL jarURL = jarFile.toURI().toURL(); + ClassLoader classLoader = new URLClassLoader(new URL[]{jarURL}, this.getClass().getClassLoader()); + Attributes m = new JarFile(jarFile).getManifest().getMainAttributes(); + String contractMainClass = m.getValue(Attributes.Name.MAIN_CLASS); + Class mainClass = classLoader.loadClass(contractMainClass); + ContractType.resolve(mainClass); + } + private List blackNameList(Properties config) { return blackList(config, BLACK_NAME_LIST); } @@ -320,14 +313,14 @@ public class ContractVerifyMojo extends AbstractMojo { // 首先进行Copy处理 copy(srcJar, dstJar); - byte[] txtBytes = jdChainTxt(FileUtils.readFileToByteArray(dstJar)).getBytes(StandardCharsets.UTF_8); + byte[] txtBytes = contractMF(FileUtils.readFileToByteArray(dstJar)).getBytes(StandardCharsets.UTF_8); String finalJarPath = project.getBuild().getDirectory() + File.separator + finalName + "-jdchain.jar"; File finalJar = new File(finalJarPath); - copy(dstJar, finalJar, jdChainMetaTxtJarEntry(), txtBytes, null); + copy(dstJar, finalJar, contractMFJarEntry(), txtBytes, null); // 删除临时文件 FileUtils.forceDelete(dstJar); @@ -423,8 +416,9 @@ public class ContractVerifyMojo extends AbstractMojo { if (totalPackage.endsWith("*")) { this.packageName = totalPackage.substring(0, totalPackage.length() - 2).trim(); this.isTotal = true; + } else { + this.packageName = totalPackage; } - this.packageName = totalPackage; } public String getPackageName() { diff --git a/source/contract/contract-maven-plugin/src/main/resources/config.properties b/source/contract/contract-maven-plugin/src/main/resources/config.properties index 4a176409..b54de2fb 100644 --- a/source/contract/contract-maven-plugin/src/main/resources/config.properties +++ b/source/contract/contract-maven-plugin/src/main/resources/config.properties @@ -1,8 +1,8 @@ -#black.name.list:打包为合约Jar后,每个Class文件不允许使用的名称,默认不允许使用com.jd.blockchain.* -black.name.list=com.jd.blockchain.* +#black.name.list:打包为合约Jar后,每个Class文件不允许使用或包含的名称,默认不允许使用com.jd.blockchain.*及一些内部已经引用的包 +black.name.list=com.jd.blockchain.*, com.alibaba.fastjson.*, org.apache.commons.io.*, org.apache.commons.codec.*, io.netty.* #black.package.list:打包为合约中的每个Class都不允许使用的包列表,某个包下面的所有包通过.*表示 -black.package.list=java.io.*, java.net.*, org.apache.commons.io.* +black.package.list=java.io.*, java.nio.*, java.net.*, org.apache.commons.io.* #black.class.list:打包为合约中的每个Class都不允许使用的类列表 black.class.list=java.util.Random, com.jd.blockchain.ledger.BlockchainKeyGenerator \ No newline at end of file diff --git a/source/contract/contract-maven-plugin/src/test/java/com/jd/blockchain/ledger/ContractVerifyTest.java b/source/contract/contract-maven-plugin/src/test/java/com/jd/blockchain/ledger/ContractVerifyTest.java index dc5d2541..d57ab5d0 100644 --- a/source/contract/contract-maven-plugin/src/test/java/com/jd/blockchain/ledger/ContractVerifyTest.java +++ b/source/contract/contract-maven-plugin/src/test/java/com/jd/blockchain/ledger/ContractVerifyTest.java @@ -18,7 +18,7 @@ public class ContractVerifyTest { @Before public void testInit() { project = mavenProjectInit(); - finalName = "complex.jar"; + finalName = "complex"; } @Test diff --git a/source/gateway/src/main/java/com/jd/blockchain/gateway/service/GatewayInterceptServiceHandler.java b/source/gateway/src/main/java/com/jd/blockchain/gateway/service/GatewayInterceptServiceHandler.java index b70bee5d..2f3d215e 100644 --- a/source/gateway/src/main/java/com/jd/blockchain/gateway/service/GatewayInterceptServiceHandler.java +++ b/source/gateway/src/main/java/com/jd/blockchain/gateway/service/GatewayInterceptServiceHandler.java @@ -5,6 +5,7 @@ import com.jd.blockchain.ledger.ContractCodeDeployOperation; import com.jd.blockchain.ledger.Operation; import com.jd.blockchain.ledger.TransactionRequest; import com.jd.blockchain.utils.IllegalDataException; +import com.jd.blockchain.utils.jar.ContractJarUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -29,14 +30,7 @@ public class GatewayInterceptServiceHandler implements GatewayInterceptService { } private void contractCheck(final ContractCodeDeployOperation contractOP) { - // - byte[] chainCode = contractOP.getChainCode(); - if (chainCode == null || chainCode.length == 0) { - throw new IllegalDataException("Contract's content is empty !!!"); - } - - - - + // 校验chainCode + ContractJarUtils.verify(contractOP.getChainCode()); } } diff --git a/source/gateway/src/main/java/com/jd/blockchain/gateway/web/TxProcessingController.java b/source/gateway/src/main/java/com/jd/blockchain/gateway/web/TxProcessingController.java index 3ee571d9..5405cc98 100644 --- a/source/gateway/src/main/java/com/jd/blockchain/gateway/web/TxProcessingController.java +++ b/source/gateway/src/main/java/com/jd/blockchain/gateway/web/TxProcessingController.java @@ -1,5 +1,6 @@ package com.jd.blockchain.gateway.web; +import com.jd.blockchain.gateway.service.GatewayInterceptService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; @@ -30,9 +31,15 @@ public class TxProcessingController implements TransactionService { @Autowired private PeerService peerService; + @Autowired + private GatewayInterceptService interceptService; + @RequestMapping(path = "rpc/tx", method = RequestMethod.POST, consumes = BinaryMessageConverter.CONTENT_TYPE_VALUE, produces = BinaryMessageConverter.CONTENT_TYPE_VALUE) @Override public @ResponseBody TransactionResponse process(@RequestBody TransactionRequest txRequest) { + // 拦截请求进行校验 + interceptService.intercept(txRequest); + // 检查交易请求的信息是否完整; HashDigest ledgerHash = txRequest.getTransactionContent().getLedgerHash(); if (ledgerHash == null) { diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/handles/ContractCodeDeployOperationHandle.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/handles/ContractCodeDeployOperationHandle.java index e18c9304..fd4dc617 100644 --- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/handles/ContractCodeDeployOperationHandle.java +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/handles/ContractCodeDeployOperationHandle.java @@ -1,5 +1,6 @@ package com.jd.blockchain.ledger.core.impl.handles; +import com.jd.blockchain.utils.jar.ContractJarUtils; import org.springframework.stereotype.Service; import com.jd.blockchain.ledger.BytesValue; @@ -22,8 +23,12 @@ public class ContractCodeDeployOperationHandle implements OperationHandle { // TODO: 请求者应该提供合约账户的公钥签名,已确定注册的地址的唯一性; + byte[] chainCode = contractOP.getChainCode(); + // 校验合约代码,不通过会抛出异常 + ContractJarUtils.verify(chainCode); + dataset.getContractAccountSet().deploy(contractOP.getContractID().getAddress(), - contractOP.getContractID().getPubKey(), contractOP.getAddressSignature(), contractOP.getChainCode()); + contractOP.getContractID().getPubKey(), contractOP.getAddressSignature(), chainCode); return null; } @@ -37,5 +42,4 @@ public class ContractCodeDeployOperationHandle implements OperationHandle { public boolean support(Class operationType) { return ContractCodeDeployOperation.class.isAssignableFrom(operationType); } - } diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/BlockchainOperationFactory.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/BlockchainOperationFactory.java index a8f34045..93f0e3c7 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/BlockchainOperationFactory.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/BlockchainOperationFactory.java @@ -260,8 +260,6 @@ public class BlockchainOperationFactory implements ClientOperator, LedgerInitOpe private class ContractCodeDeployOperationBuilderFilter implements ContractCodeDeployOperationBuilder { @Override public ContractCodeDeployOperation deploy(BlockchainIdentity id, byte[] chainCode) { - // 校验chainCode - ContractJarUtils.verify(chainCode); // 校验成功后发布 ContractCodeDeployOperation op = CONTRACT_CODE_DEPLOY_OP_BUILDER.deploy(id, chainCode); operationList.add(op); diff --git a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/jar/ContractJarUtils.java b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/jar/ContractJarUtils.java index a59512db..5ec66dde 100644 --- a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/jar/ContractJarUtils.java +++ b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/jar/ContractJarUtils.java @@ -15,13 +15,16 @@ import java.util.jar.JarOutputStream; public class ContractJarUtils { - private static final String JDCHAIN_META = "META-INF/CONTRACT.MF"; + private static final String CONTRACT_MF = "META-INF/CONTRACT.MF"; private static final int JDCHAIN_HASH_LENGTH = 69; private static final Random FILE_RANDOM = new Random(); public static void verify(byte[] chainCode) { + if (chainCode == null || chainCode.length == 0) { + throw new IllegalStateException("ChainCode is empty !!!"); + } // 首先生成合约文件 File jarFile = newJarFile(); try { @@ -42,14 +45,14 @@ public class ContractJarUtils { private static void verify(File jarFile) throws Exception { // 首先判断jarFile中是否含有META-INF/JDCHAIN.TXT,并将其读出 - URL jarUrl = new URL("jar:file:" + jarFile.getPath() + "!/" + JDCHAIN_META); + URL jarUrl = new URL("jar:file:" + jarFile.getPath() + "!/" + CONTRACT_MF); InputStream inputStream = jarUrl.openStream(); if (inputStream == null) { - throw new IllegalStateException(JDCHAIN_META + " IS NULL !!!"); + throw new IllegalStateException(CONTRACT_MF + " IS NULL !!!"); } byte[] bytes = IOUtils.toByteArray(inputStream); if (bytes == null || bytes.length != JDCHAIN_HASH_LENGTH) { - throw new IllegalStateException(JDCHAIN_META + " IS Illegal !!!"); + throw new IllegalStateException(CONTRACT_MF + " IS Illegal !!!"); } // 获取对应的Hash内容 String txt = new String(bytes, StandardCharsets.UTF_8); @@ -58,10 +61,10 @@ public class ContractJarUtils { File tempJar = newJarFile(); // 复制除JDCHAIN.TXT之外的部分 - copy(jarFile, tempJar, null, null, JDCHAIN_META); + copy(jarFile, tempJar, null, null, CONTRACT_MF); // 生成新Jar包对应的Hash内容 - String verifyTxt = jdChainTxt(FileUtils.readFileToByteArray(tempJar)); + String verifyTxt = contractMF(FileUtils.readFileToByteArray(tempJar)); // 删除临时文件 FileUtils.forceDelete(tempJar); @@ -103,13 +106,13 @@ public class ContractJarUtils { jarFile.close(); } - public static String jdChainTxt(byte[] content) { + public static String contractMF(byte[] content) { // hash=Hex(hash(content)) return "hash:" + DigestUtils.sha256Hex(content); } - public static JarEntry jdChainMetaTxtJarEntry() { - return new JarEntry(JDCHAIN_META); + public static JarEntry contractMFJarEntry() { + return new JarEntry(CONTRACT_MF); } private static byte[] readStream(InputStream inputStream) { diff --git a/source/utils/utils-common/src/test/java/test/my/utils/ContractJarUtilsTest.java b/source/utils/utils-common/src/test/java/test/my/utils/ContractJarUtilsTest.java index 9caa6da2..02376434 100644 --- a/source/utils/utils-common/src/test/java/test/my/utils/ContractJarUtilsTest.java +++ b/source/utils/utils-common/src/test/java/test/my/utils/ContractJarUtilsTest.java @@ -34,14 +34,14 @@ public class ContractJarUtilsTest { // 首先进行Copy处理 copy(srcJar, dstJar); - byte[] txtBytes = jdChainTxt(FileUtils.readFileToByteArray(dstJar)).getBytes(StandardCharsets.UTF_8); + byte[] txtBytes = contractMF(FileUtils.readFileToByteArray(dstJar)).getBytes(StandardCharsets.UTF_8); String finalJarPath = classPath + File.separator + jarName + "-jdchain.jar"; File finalJar = new File(finalJarPath); - copy(dstJar, finalJar, jdChainMetaTxtJarEntry(), txtBytes, null); + copy(dstJar, finalJar, contractMFJarEntry(), txtBytes, null); // 删除临时文件 FileUtils.forceDelete(dstJar);