@@ -41,6 +41,20 @@ public class ContractResolveEngine { | |||
private static final String BLACK_NAME_LIST = "black.name.list"; | |||
private static List<ContractPackage> blackNameList; | |||
private static List<ContractPackage> blackPackageList; | |||
private static Set<String> blackClassSet; | |||
static { | |||
try { | |||
configInit(); | |||
} catch (Exception e) { | |||
throw new IllegalStateException(e); | |||
} | |||
} | |||
private Log LOGGER; | |||
private MavenProject project; | |||
@@ -87,14 +101,6 @@ public class ContractResolveEngine { | |||
throw e; | |||
} | |||
Properties config = loadConfig(); | |||
List<ContractPackage> blackNameList = blackNameList(config); | |||
List<ContractPackage> blackPackageList = blackPackageList(config); | |||
Set<String> blackClassSet = blackClassSet(config); | |||
LinkedList<String> totalClassList = loadAllClass(jarFile); | |||
// 该项目路径 | |||
String projectDir = project.getBasedir().getPath(); | |||
@@ -230,34 +236,32 @@ public class ContractResolveEngine { | |||
LOGGER.debug(String.format("Verify Jar [%s] 's MainClass end...", jarFile.getName())); | |||
} | |||
private List<ContractPackage> blackNameList(Properties config) { | |||
private static List<ContractPackage> blackNameList(Properties config) { | |||
return blackList(config, BLACK_NAME_LIST); | |||
} | |||
private Set<String> blackClassSet(Properties config) { | |||
private static Set<String> blackClassSet(Properties config) { | |||
Set<String> blackClassSet = new HashSet<>(); | |||
String attrProp = config.getProperty(BLACK_CLASS_LIST); | |||
if (attrProp != null && attrProp.length() > 0) { | |||
String[] attrPropArray = attrProp.split(","); | |||
for (String attr : attrPropArray) { | |||
LOGGER.info(String.format("Config [%s] -> [%s]", BLACK_CLASS_LIST, attr)); | |||
blackClassSet.add(attr.trim()); | |||
} | |||
} | |||
return blackClassSet; | |||
} | |||
private List<ContractPackage> blackPackageList(Properties config) { | |||
private static List<ContractPackage> blackPackageList(Properties config) { | |||
return blackList(config, BLACK_PACKAGE_LIST); | |||
} | |||
private List<ContractPackage> blackList(Properties config, String attrName) { | |||
private static List<ContractPackage> blackList(Properties config, String attrName) { | |||
List<ContractPackage> list = new ArrayList<>(); | |||
String attrProp = config.getProperty(attrName); | |||
if (attrProp != null || attrProp.length() > 0) { | |||
String[] attrPropArray = attrProp.split(","); | |||
for (String attr : attrPropArray) { | |||
LOGGER.info(String.format("Config [%s] -> [%s]", attrName, attr)); | |||
list.add(new ContractPackage(attr)); | |||
} | |||
} | |||
@@ -359,11 +363,21 @@ public class ContractResolveEngine { | |||
return finalJar; | |||
} | |||
private Properties loadConfig() throws Exception { | |||
private static void configInit() throws Exception { | |||
Properties config = loadConfig(); | |||
blackNameList = blackNameList(config); | |||
blackPackageList = blackPackageList(config); | |||
blackClassSet = blackClassSet(config); | |||
} | |||
private static Properties loadConfig() throws Exception { | |||
Properties properties = new Properties(); | |||
properties.load(this.getClass().getClassLoader().getResourceAsStream(CONFIG)); | |||
properties.load(ContractResolveEngine.class.getResourceAsStream(File.separator + CONFIG)); | |||
return properties; | |||
} | |||
@@ -39,13 +39,4 @@ public class JVMContractEventSendOperationHandle extends AbstractContractEventHa | |||
} | |||
return contractCode; | |||
} | |||
// @Override | |||
// public AsyncFuture<byte[]> asyncProcess(Operation op, LedgerDataSet newBlockDataset, | |||
// TransactionRequestContext requestContext, LedgerDataSet previousBlockDataset, | |||
// OperationHandleContext handleContext, LedgerService ledgerService) { | |||
// // TODO Auto-generated method stub | |||
// return null; | |||
// } | |||
} |
@@ -37,7 +37,6 @@ | |||
<groupId>com.jd.blockchain</groupId> | |||
<artifactId>crypto-classic</artifactId> | |||
<version>${project.version}</version> | |||
<scope>test</scope> | |||
</dependency> | |||
</dependencies> | |||
@@ -2,11 +2,10 @@ package com.jd.blockchain.runtime; | |||
import java.io.File; | |||
import java.io.IOException; | |||
import java.io.InputStream; | |||
import java.net.URL; | |||
import java.net.URLClassLoader; | |||
import java.util.ArrayList; | |||
import java.util.List; | |||
import java.util.Map; | |||
import java.util.*; | |||
import java.util.concurrent.ConcurrentHashMap; | |||
import java.util.jar.Attributes; | |||
import java.util.jar.JarFile; | |||
@@ -16,7 +15,7 @@ import com.jd.blockchain.utils.io.RuntimeIOException; | |||
public abstract class RuntimeContext { | |||
public static interface Environment{ | |||
public static interface Environment { | |||
boolean isProductMode(); | |||
@@ -24,6 +23,7 @@ public abstract class RuntimeContext { | |||
private static final Object mutex = new Object(); | |||
private static volatile RuntimeContext runtimeContext; | |||
public static RuntimeContext get() { | |||
@@ -202,8 +202,78 @@ public abstract class RuntimeContext { | |||
@Override | |||
protected URLClassLoader createDynamicModuleClassLoader(URL jarURL) { | |||
return new URLClassLoader(new URL[] { jarURL }, RuntimeContext.class.getClassLoader()); | |||
return new ContractURLClassLoader(jarURL, RuntimeContext.class.getClassLoader()); | |||
} | |||
} | |||
static class ContractURLClassLoader extends URLClassLoader { | |||
private static final String BLACK_CONFIG = "black.config"; | |||
private static final Set<String> BLACK_CLASSES = new HashSet<>(); | |||
private static final Set<String> BLACK_PACKAGES = new HashSet<>(); | |||
static { | |||
initBlacks(); | |||
} | |||
public ContractURLClassLoader(URL contractJarURL, ClassLoader parent) { | |||
super(new URL[] { contractJarURL }, parent); | |||
} | |||
@Override | |||
public Class<?> loadClass(String name) throws ClassNotFoundException { | |||
if (BLACK_CLASSES.contains(name)) { | |||
throw new IllegalStateException(String.format("Contract cannot use Class [%s]", name)); | |||
} else { | |||
// 判断该包是否是黑名单 | |||
String trimName = name.trim(); | |||
String packageName = trimName.substring(0, trimName.length() - 2); | |||
if (BLACK_PACKAGES.contains(packageName)) { | |||
throw new IllegalStateException(String.format("Contract cannot use Class [%s]", name)); | |||
} | |||
} | |||
return super.loadClass(name); | |||
} | |||
private static void initBlacks() { | |||
try { | |||
InputStream inputStream = ContractURLClassLoader.class.getResourceAsStream(File.separator + BLACK_CONFIG); | |||
String text = FileUtils.readText(inputStream); | |||
String[] textArray = text.split("\n"); | |||
for (String setting : textArray) { | |||
// 支持按照逗号分隔 | |||
if (setting == null || setting.length() == 0) { | |||
continue; | |||
} | |||
String[] settingArray = setting.split(","); | |||
for (String set : settingArray) { | |||
String totalClass = set.trim(); | |||
if (totalClass.endsWith("*")) { | |||
// 说明是包,获取具体包名 | |||
String packageName = totalClass.substring(0, totalClass.length() - 2); | |||
BLACK_PACKAGES.add(packageName); | |||
} else { | |||
// 具体的类名,直接放入集合 | |||
BLACK_CLASSES.add(totalClass); | |||
} | |||
} | |||
} | |||
} catch (Exception e) { | |||
throw new IllegalStateException(e); | |||
} | |||
} | |||
public static void main(String[] args) { | |||
for (String s : BLACK_CLASSES) { | |||
System.out.println(s); | |||
} | |||
for (String s : BLACK_PACKAGES) { | |||
System.out.println(s); | |||
} | |||
} | |||
} | |||
} |
@@ -0,0 +1,2 @@ | |||
java.util.Random, com.jd.blockchain.ledger.BlockchainKeyGenerator | |||
java.io.*, java.nio.*, java.net.*, org.apache.commons.io.* |
@@ -0,0 +1,67 @@ | |||
package com.jd.blockchain.sdk.samples; | |||
import com.jd.blockchain.contract.TransferContract; | |||
import com.jd.blockchain.ledger.*; | |||
import com.jd.blockchain.transaction.GenericValueHolder; | |||
import com.jd.blockchain.utils.Bytes; | |||
import com.jd.chain.contracts.ContractTestInf; | |||
import static com.jd.blockchain.sdk.samples.SDKDemo_Constant.readChainCodes; | |||
import static com.jd.blockchain.transaction.ContractReturnValue.decode; | |||
public class SDK_Contract_Check_Demo extends SDK_Base_Demo { | |||
public static void main(String[] args) { | |||
new SDK_Contract_Check_Demo().executeContract(); | |||
} | |||
public void executeContract() { | |||
// 发布jar包 | |||
// 定义交易模板 | |||
TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash); | |||
// 将jar包转换为二进制数据 | |||
byte[] contractCode = readChainCodes("contract-jdchain.jar"); | |||
// 生成一个合约账号 | |||
BlockchainKeypair contractDeployKey = BlockchainKeyGenerator.getInstance().generate(); | |||
// 生成发布合约操作 | |||
txTpl.contracts().deploy(contractDeployKey.getIdentity(), contractCode); | |||
// 生成预发布交易; | |||
PreparedTransaction ptx = txTpl.prepare(); | |||
// 对交易进行签名 | |||
ptx.sign(adminKey); | |||
// 提交并等待共识返回; | |||
TransactionResponse txResp = ptx.commit(); | |||
// 获取合约地址 | |||
Bytes contractAddress = contractDeployKey.getAddress(); | |||
// 打印交易返回信息 | |||
System.out.printf("Tx[%s] -> BlockHeight = %s, BlockHash = %s, isSuccess = %s, ExecutionState = %s \r\n", | |||
txResp.getContentHash().toBase58(), txResp.getBlockHeight(), txResp.getBlockHash().toBase58(), | |||
txResp.isSuccess(), txResp.getExecutionState()); | |||
// 打印合约地址 | |||
System.out.printf("ContractAddress = %s \r\n", contractAddress.toBase58()); | |||
// 执行合约 | |||
exeContract(contractAddress); | |||
} | |||
private void exeContract(Bytes contractAddress) { | |||
TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash); | |||
ContractTestInf contract = txTpl.contract(contractAddress, ContractTestInf.class); | |||
GenericValueHolder<String> result = decode(contract.randomChars(1024)); | |||
commit(txTpl); | |||
String random = result.get(); | |||
System.out.println(random); | |||
} | |||
} |
@@ -0,0 +1,14 @@ | |||
package com.jd.chain.contracts; | |||
import com.jd.blockchain.contract.Contract; | |||
import com.jd.blockchain.contract.ContractEvent; | |||
@Contract | |||
public interface ContractTestInf { | |||
@ContractEvent(name = "print") | |||
void print(String name, int age); | |||
@ContractEvent(name = "random") | |||
String randomChars(int max); | |||
} |