@@ -15,16 +15,24 @@ public class ContractCompileMojo extends SingleAssemblyMojo { | |||||
// 要求必须有MainClass | // 要求必须有MainClass | ||||
try { | try { | ||||
String mainClass = super.getJarArchiveConfiguration().getManifest().getMainClass(); | String mainClass = super.getJarArchiveConfiguration().getManifest().getMainClass(); | ||||
// 校验MainClass,要求MainClass必须不能为空 | |||||
if (mainClass == null || mainClass.length() == 0) { | |||||
throw new MojoFailureException("MainClass is NULL !!!"); | |||||
} | |||||
super.getLog().debug("MainClass is " + mainClass); | super.getLog().debug("MainClass is " + mainClass); | ||||
} catch (Exception e) { | } catch (Exception e) { | ||||
throw new MojoFailureException("MainClass is null: " + e.getMessage(), e ); | throw new MojoFailureException("MainClass is null: " + e.getMessage(), e ); | ||||
} | } | ||||
// 此参数用于设置将所有第三方依赖的Jar包打散为.class,与主代码打包在一起,生成一个jar包 | |||||
super.setDescriptorRefs(new String[]{JAR_DEPENDENCE}); | super.setDescriptorRefs(new String[]{JAR_DEPENDENCE}); | ||||
// 执行打包命令 | |||||
super.execute(); | super.execute(); | ||||
ContractResolveEngine engine = new ContractResolveEngine(getLog(), getProject(), getFinalName()); | ContractResolveEngine engine = new ContractResolveEngine(getLog(), getProject(), getFinalName()); | ||||
// 打包并进行校验 | |||||
engine.compileAndVerify(); | engine.compileAndVerify(); | ||||
} | } | ||||
} | } |
@@ -20,9 +20,9 @@ import java.util.jar.Attributes; | |||||
import java.util.jar.JarEntry; | import java.util.jar.JarEntry; | ||||
import java.util.jar.JarFile; | import java.util.jar.JarFile; | ||||
import static com.jd.blockchain.contract.ContractJarUtils.*; | |||||
import static com.jd.blockchain.contract.maven.ContractCompileMojo.JAR_DEPENDENCE; | import static com.jd.blockchain.contract.maven.ContractCompileMojo.JAR_DEPENDENCE; | ||||
import static com.jd.blockchain.utils.decompiler.utils.DecompilerUtils.decompileJarFile; | import static com.jd.blockchain.utils.decompiler.utils.DecompilerUtils.decompileJarFile; | ||||
import static com.jd.blockchain.utils.jar.ContractJarUtils.*; | |||||
public class ContractResolveEngine { | public class ContractResolveEngine { | ||||
@@ -1,11 +1,10 @@ | |||||
package com.jd.blockchain.gateway.service; | package com.jd.blockchain.gateway.service; | ||||
import com.jd.blockchain.contract.ContractJarUtils; | |||||
import com.jd.blockchain.gateway.PeerService; | import com.jd.blockchain.gateway.PeerService; | ||||
import com.jd.blockchain.ledger.ContractCodeDeployOperation; | import com.jd.blockchain.ledger.ContractCodeDeployOperation; | ||||
import com.jd.blockchain.ledger.Operation; | import com.jd.blockchain.ledger.Operation; | ||||
import com.jd.blockchain.ledger.TransactionRequest; | 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.beans.factory.annotation.Autowired; | ||||
import org.springframework.stereotype.Service; | import org.springframework.stereotype.Service; | ||||
@@ -18,7 +18,7 @@ import com.jd.blockchain.ledger.core.impl.LedgerQueryService; | |||||
import com.jd.blockchain.ledger.core.impl.OperationHandleContext; | import com.jd.blockchain.ledger.core.impl.OperationHandleContext; | ||||
@Service | @Service | ||||
public abstract class AbtractContractEventHandle implements OperationHandle { | |||||
public abstract class AbstractContractEventHandle implements OperationHandle { | |||||
@Override | @Override | ||||
public boolean support(Class<?> operationType) { | public boolean support(Class<?> operationType) { |
@@ -1,6 +1,6 @@ | |||||
package com.jd.blockchain.ledger.core.impl.handles; | package com.jd.blockchain.ledger.core.impl.handles; | ||||
import com.jd.blockchain.utils.jar.ContractJarUtils; | |||||
import com.jd.blockchain.contract.ContractJarUtils; | |||||
import org.springframework.stereotype.Service; | import org.springframework.stereotype.Service; | ||||
import com.jd.blockchain.ledger.BytesValue; | import com.jd.blockchain.ledger.BytesValue; | ||||
@@ -5,12 +5,17 @@ import com.jd.blockchain.contract.engine.ContractEngine; | |||||
import com.jd.blockchain.contract.engine.ContractServiceProviders; | import com.jd.blockchain.contract.engine.ContractServiceProviders; | ||||
import com.jd.blockchain.ledger.core.ContractAccount; | import com.jd.blockchain.ledger.core.ContractAccount; | ||||
import java.util.concurrent.locks.Lock; | |||||
import java.util.concurrent.locks.ReentrantLock; | |||||
import static com.jd.blockchain.utils.BaseConstant.CONTRACT_SERVICE_PROVIDER; | import static com.jd.blockchain.utils.BaseConstant.CONTRACT_SERVICE_PROVIDER; | ||||
public class JVMContractEventSendOperationHandle extends AbtractContractEventHandle { | |||||
public class JVMContractEventSendOperationHandle extends AbstractContractEventHandle { | |||||
private static final ContractEngine JVM_ENGINE; | private static final ContractEngine JVM_ENGINE; | ||||
private static final Lock JVM_LOAD_LOCK = new ReentrantLock(); | |||||
static { | static { | ||||
JVM_ENGINE = ContractServiceProviders.getProvider(CONTRACT_SERVICE_PROVIDER).getEngine(); | JVM_ENGINE = ContractServiceProviders.getProvider(CONTRACT_SERVICE_PROVIDER).getEngine(); | ||||
} | } | ||||
@@ -19,9 +24,18 @@ public class JVMContractEventSendOperationHandle extends AbtractContractEventHan | |||||
protected ContractCode loadContractCode(ContractAccount contract) { | protected ContractCode loadContractCode(ContractAccount contract) { | ||||
ContractCode contractCode = JVM_ENGINE.getContract(contract.getAddress(), contract.getChaincodeVersion()); | ContractCode contractCode = JVM_ENGINE.getContract(contract.getAddress(), contract.getChaincodeVersion()); | ||||
if (contractCode == null) { | if (contractCode == null) { | ||||
// 装载合约; | |||||
contractCode = JVM_ENGINE.setupContract(contract.getAddress(), contract.getChaincodeVersion(), | |||||
contract.getChainCode()); | |||||
JVM_LOAD_LOCK.lock(); | |||||
try { | |||||
// Double Check | |||||
contractCode = JVM_ENGINE.getContract(contract.getAddress(), contract.getChaincodeVersion()); | |||||
if (contractCode == null) { | |||||
// 装载合约; | |||||
contractCode = JVM_ENGINE.setupContract(contract.getAddress(), contract.getChaincodeVersion(), | |||||
contract.getChainCode()); | |||||
} | |||||
} finally { | |||||
JVM_LOAD_LOCK.unlock(); | |||||
} | |||||
} | } | ||||
return contractCode; | return contractCode; | ||||
} | } | ||||
@@ -8,10 +8,10 @@ import com.jd.blockchain.contract.engine.ContractCode; | |||||
import com.jd.blockchain.contract.jvm.AbstractContractCode; | import com.jd.blockchain.contract.jvm.AbstractContractCode; | ||||
import com.jd.blockchain.contract.jvm.ContractDefinition; | import com.jd.blockchain.contract.jvm.ContractDefinition; | ||||
import com.jd.blockchain.ledger.core.ContractAccount; | import com.jd.blockchain.ledger.core.ContractAccount; | ||||
import com.jd.blockchain.ledger.core.impl.handles.AbtractContractEventHandle; | |||||
import com.jd.blockchain.ledger.core.impl.handles.AbstractContractEventHandle; | |||||
import com.jd.blockchain.utils.Bytes; | import com.jd.blockchain.utils.Bytes; | ||||
public class ContractInvokingHandle extends AbtractContractEventHandle { | |||||
public class ContractInvokingHandle extends AbstractContractEventHandle { | |||||
private Map<Bytes, ContractCode> contractInstances = new ConcurrentHashMap<Bytes, ContractCode>(); | private Map<Bytes, ContractCode> contractInstances = new ConcurrentHashMap<Bytes, ContractCode>(); | ||||
@@ -1,5 +1,9 @@ | |||||
package com.jd.blockchain.utils.jar; | |||||
package com.jd.blockchain.contract; | |||||
import com.jd.blockchain.crypto.Crypto; | |||||
import com.jd.blockchain.crypto.HashDigest; | |||||
import com.jd.blockchain.crypto.HashFunction; | |||||
import com.jd.blockchain.utils.io.BytesUtils; | |||||
import org.apache.commons.codec.digest.DigestUtils; | import org.apache.commons.codec.digest.DigestUtils; | ||||
import org.apache.commons.io.FileUtils; | import org.apache.commons.io.FileUtils; | ||||
import org.apache.commons.io.IOUtils; | import org.apache.commons.io.IOUtils; | ||||
@@ -17,13 +21,15 @@ public class ContractJarUtils { | |||||
private static final String CONTRACT_MF = "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 HashFunction HASH_FUNCTION = Crypto.getHashFunction("SHA256"); | |||||
private static final Random FILE_RANDOM = new Random(); | private static final Random FILE_RANDOM = new Random(); | ||||
private static final byte[] JDCHAIN_MARK = "JDChain".getBytes(StandardCharsets.UTF_8); | |||||
public static void verify(byte[] chainCode) { | public static void verify(byte[] chainCode) { | ||||
if (chainCode == null || chainCode.length == 0) { | if (chainCode == null || chainCode.length == 0) { | ||||
throw new IllegalStateException("ChainCode is empty !!!"); | |||||
throw new IllegalStateException("Contract's chaincode is empty !!!"); | |||||
} | } | ||||
// 首先生成合约文件 | // 首先生成合约文件 | ||||
File jarFile = newJarFile(); | File jarFile = newJarFile(); | ||||
@@ -51,7 +57,7 @@ public class ContractJarUtils { | |||||
throw new IllegalStateException(CONTRACT_MF + " IS NULL !!!"); | throw new IllegalStateException(CONTRACT_MF + " IS NULL !!!"); | ||||
} | } | ||||
byte[] bytes = IOUtils.toByteArray(inputStream); | byte[] bytes = IOUtils.toByteArray(inputStream); | ||||
if (bytes == null || bytes.length != JDCHAIN_HASH_LENGTH) { | |||||
if (bytes == null || bytes.length == 0) { | |||||
throw new IllegalStateException(CONTRACT_MF + " IS Illegal !!!"); | throw new IllegalStateException(CONTRACT_MF + " IS Illegal !!!"); | ||||
} | } | ||||
// 获取对应的Hash内容 | // 获取对应的Hash内容 | ||||
@@ -107,8 +113,8 @@ public class ContractJarUtils { | |||||
} | } | ||||
public static String contractMF(byte[] content) { | public static String contractMF(byte[] content) { | ||||
// hash=Hex(hash(content)) | |||||
return "hash:" + DigestUtils.sha256Hex(content); | |||||
HashDigest hashDigest = HASH_FUNCTION.hash(BytesUtils.concat(content, JDCHAIN_MARK)); | |||||
return "hash:" + hashDigest.toBase58(); | |||||
} | } | ||||
public static JarEntry contractMFJarEntry() { | public static JarEntry contractMFJarEntry() { |
@@ -1,31 +1,11 @@ | |||||
package com.jd.blockchain.transaction; | package com.jd.blockchain.transaction; | ||||
import java.io.*; | |||||
import java.net.URL; | |||||
import java.nio.charset.StandardCharsets; | |||||
import com.jd.blockchain.ledger.*; | |||||
import com.jd.blockchain.utils.Bytes; | |||||
import java.util.ArrayList; | import java.util.ArrayList; | ||||
import java.util.Collection; | import java.util.Collection; | ||||
import java.util.Enumeration; | |||||
import java.util.List; | import java.util.List; | ||||
import java.util.jar.JarEntry; | |||||
import java.util.jar.JarFile; | |||||
import java.util.jar.JarOutputStream; | |||||
import com.jd.blockchain.ledger.BlockchainIdentity; | |||||
import com.jd.blockchain.ledger.BytesValue; | |||||
import com.jd.blockchain.ledger.BytesValueList; | |||||
import com.jd.blockchain.ledger.ContractCodeDeployOperation; | |||||
import com.jd.blockchain.ledger.ContractEventSendOperation; | |||||
import com.jd.blockchain.ledger.DataAccountKVSetOperation; | |||||
import com.jd.blockchain.ledger.DataAccountRegisterOperation; | |||||
import com.jd.blockchain.ledger.LedgerInitOperation; | |||||
import com.jd.blockchain.ledger.LedgerInitSetting; | |||||
import com.jd.blockchain.ledger.Operation; | |||||
import com.jd.blockchain.ledger.UserRegisterOperation; | |||||
import com.jd.blockchain.utils.Bytes; | |||||
import com.jd.blockchain.utils.jar.ContractJarUtils; | |||||
import org.apache.commons.codec.digest.DigestUtils; | |||||
import org.apache.commons.io.FileUtils; | |||||
/** | /** | ||||
* @author huanghaiquan | * @author huanghaiquan | ||||
@@ -1,4 +1,4 @@ | |||||
package test.my.utils; | |||||
package test.com.jd.blockchain.ledger.data; | |||||
import org.apache.commons.io.FileUtils; | import org.apache.commons.io.FileUtils; | ||||
import org.junit.Test; | import org.junit.Test; | ||||
@@ -7,7 +7,7 @@ import org.springframework.core.io.ClassPathResource; | |||||
import java.io.File; | import java.io.File; | ||||
import java.nio.charset.StandardCharsets; | import java.nio.charset.StandardCharsets; | ||||
import static com.jd.blockchain.utils.jar.ContractJarUtils.*; | |||||
import static com.jd.blockchain.contract.ContractJarUtils.*; | |||||
import static org.junit.Assert.fail; | import static org.junit.Assert.fail; | ||||
public class ContractJarUtilsTest { | public class ContractJarUtilsTest { | ||||
@@ -59,6 +59,11 @@ public class ContractJarUtilsTest { | |||||
} catch (Exception e) { | } catch (Exception e) { | ||||
fail("Verify Fail !!"); | fail("Verify Fail !!"); | ||||
} | } | ||||
} | |||||
@Test | |||||
public void testSign() { | |||||
byte[] test = "zhangsan".getBytes(StandardCharsets.UTF_8); | |||||
System.out.println(contractMF(test)); | |||||
} | } | ||||
} | } |
@@ -91,7 +91,7 @@ public class HomeBooter { | |||||
runtimeDir.mkdirs(); | runtimeDir.mkdirs(); | ||||
} | } | ||||
// 以 ExtClassLoader 作为所有创建的ClassLoader的 Parrent; | |||||
// 以 ExtClassLoader 作为所有创建的ClassLoader的 Parent; | |||||
ClassLoader extClassLoader = HomeBooter.class.getClassLoader().getParent(); | ClassLoader extClassLoader = HomeBooter.class.getClassLoader().getParent(); | ||||
URL[] libJars = loadClassPaths(libDir); | URL[] libJars = loadClassPaths(libDir); | ||||
@@ -6,7 +6,7 @@ public class ModularFactory { | |||||
* 启动系统; | * 启动系统; | ||||
*/ | */ | ||||
public static void startSystem(String runtimeDir, boolean productMode, | public static void startSystem(String runtimeDir, boolean productMode, | ||||
ClassLoader libClassLoader,String mainClassName, ClassLoader systemClassLoader, String[] args) { | |||||
ClassLoader libClassLoader, String mainClassName, ClassLoader systemClassLoader, String[] args) { | |||||
JarsModule libModule = new JarsModule("LibModule", libClassLoader); | JarsModule libModule = new JarsModule("LibModule", libClassLoader); | ||||