Browse Source

Merge commit '933d152047999eaf5e86d16514e477ac758a941b' into feature/crypto-spi

tags/1.0.0
zhanglin33 6 years ago
parent
commit
0b30340eb2
13 changed files with 389 additions and 36 deletions
  1. +1
    -0
      source/base/src/main/java/com/jd/blockchain/consts/DataCodes.java
  2. +39
    -13
      source/contract/contract-maven-plugin/pom.xml
  3. +68
    -1
      source/contract/contract-maven-plugin/src/main/java/com/jd/blockchain/CheckImportsMojo.java
  4. +12
    -16
      source/contract/contract-maven-plugin/src/test/java/com/jd/blockchain/ledger/CheckImportsMojoTest.java
  5. +1
    -4
      source/contract/contract-maven-plugin/src/test/java/com/jd/blockchain/ledger/ContractDeployMojoTest.java
  6. +67
    -0
      source/contract/contract-maven-plugin/src/test/java/com/jd/blockchain/ledger/MyProjectStub.java
  7. +40
    -0
      source/contract/contract-maven-plugin/src/test/resources/project-to-test/AssetContract2.java
  8. +99
    -0
      source/contract/contract-maven-plugin/src/test/resources/project-to-test/AssetContractImpl2.java
  9. +24
    -0
      source/contract/contract-maven-plugin/src/test/resources/project-to-test/pom.xml
  10. BIN
      source/contract/contract-maven-plugin/src/test/resources/project-to-test/target/contract.jar
  11. +14
    -0
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ContractArgs.java
  12. +2
    -2
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/DataAccountKVSetOperationBuilderImpl.java
  13. +22
    -0
      source/sdk/sdk-samples/src/test/java/test/com/jd/blockchain/sdk/test/SDK_Contract_Test.java

+ 1
- 0
source/base/src/main/java/com/jd/blockchain/consts/DataCodes.java View File

@@ -90,6 +90,7 @@ public interface DataCodes {
public static final int CONTRACT_BIG_INT = 0xA07;
//...0xA19
public static final int CONTRACT_BIZ_CONTENT = 0xA20;
public static final int CONTRACT_ARGS = 0xA21;

public static final int HASH = 0xB00;



+ 39
- 13
source/contract/contract-maven-plugin/pom.xml View File

@@ -10,6 +10,10 @@
<artifactId>contract-maven-plugin</artifactId>
<packaging>maven-plugin</packaging>

<properties>
<maven.version>3.3.9</maven.version>
</properties>

<dependencies>
<dependency>
<groupId>com.jd.blockchain</groupId>
@@ -35,32 +39,54 @@
<version>${project.version}</version>
</dependency>


<!-- https://mvnrepository.com/artifact/org.apache.maven.plugin-tools/maven-plugin-annotations -->
<dependency>
<groupId>org.apache.maven.plugin-tools</groupId>
<artifactId>maven-plugin-annotations</artifactId>
<version>3.6.0</version>
<scope>provided</scope>
<groupId>com.github.javaparser</groupId>
<artifactId>javaparser-core</artifactId>
<version>${javaparser.version}</version>
</dependency>

<!-- new -->
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-plugin-api</artifactId>
<version>2.0</version>
<version>3.3.9</version>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-project</artifactId>
<version>2.0.6</version>
<artifactId>maven-core</artifactId>
<version>3.3.9</version>
</dependency>

<dependency>
<groupId>com.github.javaparser</groupId>
<artifactId>javaparser-core</artifactId>
<version>${javaparser.version}</version>
<groupId>org.apache.maven</groupId>
<artifactId>maven-artifact</artifactId>
<version>3.3.9</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-compat</artifactId>
<version>3.3.9</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.maven.plugin-testing</groupId>
<artifactId>maven-plugin-testing-harness</artifactId>
<scope>test</scope>
<version>3.3.0</version>
</dependency>

<!-- https://mvnrepository.com/artifact/org.apache.maven.plugin-tools/maven-plugin-annotations -->
<dependency>
<groupId>org.apache.maven.plugin-tools</groupId>
<artifactId>maven-plugin-annotations</artifactId>
<version>3.6.0</version>
<scope>provided</scope>
</dependency>
</dependencies>

<build>


+ 68
- 1
source/contract/contract-maven-plugin/src/main/java/com/jd/blockchain/CheckImportsMojo.java View File

@@ -4,6 +4,12 @@ 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.transaction.ContractType;
import com.jd.blockchain.utils.IllegalDataException;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.Mojo;
@@ -12,15 +18,28 @@ import org.apache.maven.project.MavenProject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import java.util.Properties;
import java.util.jar.Attributes;
import java.util.jar.JarFile;
import java.util.stream.Collectors;


/**
* first step, we want to parse the source code by javaParse. But it's repeated and difficult to parse the source.
* This is a try of "from Initail to Abandoned".
* Since we are good at the class, why not?
* Now we change a way of thinking, first we pre-compile the source code, then parse the *.jar.
*
* by zhaogw
* date 2019-06-05 16:17
*/
@Mojo(name = "checkImports")
public class CheckImportsMojo extends AbstractMojo {
Logger logger = LoggerFactory.getLogger(CheckImportsMojo.class);
@@ -28,6 +47,12 @@ public class CheckImportsMojo extends AbstractMojo {
@Parameter(defaultValue = "${project}", required = true, readonly = true)
private MavenProject project;

/**
* jar's name;
*/
@Parameter
private String finalName;

@Override
public void execute() throws MojoFailureException {
List<Path> sources;
@@ -40,6 +65,9 @@ public class CheckImportsMojo extends AbstractMojo {
sources = Files.find(baseDirPath, Integer.MAX_VALUE, (file, attrs) -> (file.toString().endsWith(".java"))).collect(Collectors.toList());
for (Path path : sources) {
CompilationUnit compilationUnit = JavaParser.parse(path);

compilationUnit.accept(new MethodVisitor(), null);

NodeList<ImportDeclaration> imports = compilationUnit.getImports();
for (ImportDeclaration imp : imports) {
String importName = imp.getName().asString();
@@ -49,6 +77,20 @@ public class CheckImportsMojo extends AbstractMojo {
}
}
}

//now we parse the jar;
String jarPath = project.getBuild().getDirectory()+ File.separator+finalName+".jar";
File jarFile = new File(jarPath);
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);
try {
Class mainClass = classLoader.loadClass(contractMainClass);
ContractType.resolve(mainClass);
} catch (ClassNotFoundException e) {
throw new IllegalDataException(e.getMessage());
}
}
} catch (IOException exception) {
logger.error(exception.getMessage());
@@ -57,4 +99,29 @@ public class CheckImportsMojo extends AbstractMojo {
logger.error(e.getMessage());
}
}

private class MethodVisitor extends VoidVisitorAdapter<Void> {
@Override
public void visit(MethodDeclaration n, Void arg) {
/* here you can access the attributes of the method.
this method will be called for all methods in this
CompilationUnit, including inner class methods */
logger.info("method:"+n.getName());
super.visit(n, arg);
}

@Override
public void visit(ClassOrInterfaceDeclaration n, Void arg) {
logger.info("class:"+n.getName()+" extends:"+n.getExtendedTypes()+" implements:"+n.getImplementedTypes());

super.visit(n, arg);
}

@Override
public void visit(PackageDeclaration n, Void arg) {
logger.info("package:"+n.getName());
super.visit(n, arg);
}

}
}

+ 12
- 16
source/contract/contract-maven-plugin/src/test/java/com/jd/blockchain/ledger/CheckImportsMojoTest.java View File

@@ -1,32 +1,28 @@
package com.jd.blockchain.ledger;

import com.jd.blockchain.CheckImportsMojo;
import org.apache.maven.plugin.testing.AbstractMojoTestCase;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.Properties;
import java.io.File;

/**
* @Author zhaogw
* @Date 2019/3/1 21:27
*/
public class CheckImportsMojoTest {
Logger logger = LoggerFactory.getLogger(CheckImportsMojo.class);
public class CheckImportsMojoTest extends AbstractMojoTestCase {
Logger logger = LoggerFactory.getLogger(CheckImportsMojoTest.class);

@Test
public void test1() {
try {
InputStream inputStream = CheckImportsMojo.class.getClassLoader().getResourceAsStream("config.properties");
Properties properties = new Properties();
properties.load(inputStream);
String result[] = properties.getProperty("blacklist").split(",");
logger.info(Arrays.toString(result).toString());
} catch (IOException e) {
logger.error(e.getMessage());
}
public void test1() throws Exception {
File pom = getTestFile( "src/test/resources/project-to-test/pom.xml" );
assertNotNull( pom );
assertTrue( pom.exists() );

CheckImportsMojo myMojo = (CheckImportsMojo) lookupMojo( "checkImports", pom );
assertNotNull( myMojo );
myMojo.execute();
}
}

+ 1
- 4
source/contract/contract-maven-plugin/src/test/java/com/jd/blockchain/ledger/ContractDeployMojoTest.java View File

@@ -1,10 +1,8 @@
package com.jd.blockchain.ledger;

import com.jd.blockchain.ContractDeployMojo;
import org.junit.Test;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;

/**
* for contract deploy and exe;
@@ -14,8 +12,7 @@ import java.lang.reflect.InvocationTargetException;
public class ContractDeployMojoTest {
private ContractDeployMojo contractDeployMojo = new ContractDeployMojo();

private void fieldHandle(String fieldName,Object objValue) throws NoSuchFieldException,
IllegalAccessException, NoSuchMethodException, InvocationTargetException, InstantiationException {
private void fieldHandle(String fieldName,Object objValue) throws NoSuchFieldException, IllegalAccessException {
Field field = contractDeployMojo.getClass().getDeclaredField(fieldName);//name为类Instance中的private属性
field.setAccessible(true);//=true,可访问私有变量。
Class<?> typeClass = field.getType();


+ 67
- 0
source/contract/contract-maven-plugin/src/test/java/com/jd/blockchain/ledger/MyProjectStub.java View File

@@ -0,0 +1,67 @@
package com.jd.blockchain.ledger;

import org.apache.maven.model.Build;
import org.apache.maven.model.Model;
import org.apache.maven.model.io.xpp3.MavenXpp3Reader;
import org.apache.maven.plugin.testing.stubs.MavenProjectStub;
import org.codehaus.plexus.util.ReaderFactory;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

/**
* @author zhaogw
* date 2019/6/4 18:33
*/

public class MyProjectStub extends MavenProjectStub
{
/**
* Default constructor
*/
public MyProjectStub()
{
MavenXpp3Reader pomReader = new MavenXpp3Reader();
Model model;
try
{
model = pomReader.read( ReaderFactory.newXmlReader( new File( getBasedir(), "pom.xml" ) ) );
setModel( model );
}
catch ( Exception e )
{
throw new RuntimeException( e );
}

setGroupId( model.getGroupId() );
setArtifactId( model.getArtifactId() );
setVersion( model.getVersion() );
setName( model.getName() );
setUrl( model.getUrl() );
setPackaging( model.getPackaging() );

Build build = new Build();
build.setFinalName( model.getArtifactId() );
build.setDirectory( getBasedir() + "/target" );
build.setSourceDirectory( getBasedir() + "/src/main/java" );
build.setOutputDirectory( getBasedir() + "/target/classes" );
build.setTestSourceDirectory( getBasedir() + "/src/test/java" );
build.setTestOutputDirectory( getBasedir() + "/target/test-classes" );
setBuild( build );

List compileSourceRoots = new ArrayList();
compileSourceRoots.add( getBasedir() + "/src/main/java" );
setCompileSourceRoots( compileSourceRoots );

List testCompileSourceRoots = new ArrayList();
testCompileSourceRoots.add( getBasedir() + "/src/test/java" );
setTestCompileSourceRoots( testCompileSourceRoots );
}

/** {@inheritDoc} */
public File getBasedir()
{
return new File( super.getBasedir() + "/src/test/resources/project-to-test/" );
}
}

+ 40
- 0
source/contract/contract-maven-plugin/src/test/resources/project-to-test/AssetContract2.java View File

@@ -0,0 +1,40 @@
package com.jd.blockchain.contract;

import com.jd.blockchain.ledger.ContractBizContent;
import com.jd.blockchain.utils.Bytes;

/**
* 示例:一个“资产管理”智能合约;
*
* @author zhaogw
*/
@Contract
public interface AssetContract2 {

/**
* 发行资产;
* 新发行的资产数量;
* @param assetHolderAddress
* 新发行的资产的持有账户;
*/
@ContractEvent(name = "issue-asset-0")
void issue(ContractBizContent contractBizContent, String assetHolderAddress);

/**
* 发行资产;
* 新发行的资产数量;
* @param assetHolderAddress
* 新发行的资产的持有账户;
*/
@ContractEvent(name = "issue-asset")
void issue(ContractBizContent contractBizContent, String assetHolderAddress, long cashNumber);

@ContractEvent(name = "issue-asset-2")
void issue(Bytes bytes, String assetHolderAddress, long cashNumber);

@ContractEvent(name = "issue-asset-3")
void issue(Byte byteObj, String assetHolderAddress, long cashNumber);

@ContractEvent(name = "issue-asset-4")
void issue(Byte byteObj, String assetHolderAddress, Bytes cashNumber);
}

+ 99
- 0
source/contract/contract-maven-plugin/src/test/resources/project-to-test/AssetContractImpl2.java View File

@@ -0,0 +1,99 @@
package com.jd.blockchain.contract;

import com.jd.blockchain.ledger.ContractBizContent;
import com.jd.blockchain.ledger.KVDataEntry;
import com.jd.blockchain.ledger.KVDataObject;
import com.jd.blockchain.utils.Bytes;

import java.util.Arrays;

/**
* 示例:一个“资产管理”智能合约的实现;
*
* 注: 1、实现 EventProcessingAwire 接口以便合约实例在运行时可以从上下文获得合约生命周期事件的通知; 2、实现
* AssetContract 接口定义的合约方法;
*
* @author huanghaiquan
*
*/
@Contract
public class AssetContractImpl2 implements EventProcessingAwire, AssetContract2 {
public static String KEY_TOTAL = "total";
// 合约事件上下文;
private ContractEventContext eventContext;

@Override
@ContractEvent(name = "issue-asset-0")
public void issue(ContractBizContent contractBizContent, String assetHolderAddress) {
System.out.println("input addr="+ Arrays.toString(contractBizContent.getAttrs()));
}

@Override
@ContractEvent(name = "issue-asset")
public void issue(ContractBizContent contractBizContent, String assetHolderAddress, long cashNumber) {
System.out.println("eventContext="+eventContext.getCurrentLedgerHash().toBase58());
System.out.println("getAttrs: "+Arrays.toString(contractBizContent.getAttrs())+",address="+assetHolderAddress+",cashNumber="+cashNumber);

eventContext.getLedger().dataAccount(assetHolderAddress).set(contractBizContent.getAttrs()[0], "value1",-1);
eventContext.getLedger().dataAccount(assetHolderAddress).set(contractBizContent.getAttrs()[1], 888,-1);
}

@Override
@ContractEvent(name = "issue-asset-2")
public void issue(Bytes bytes, String assetHolderAddress, long cashNumber){
System.out.println(String.format("bytes=%s,assetHolderAddress=%s,cashNumber=%d",new String(bytes.toBytes()),assetHolderAddress,cashNumber));
}

@ContractEvent(name = "issue-asset-3")
@Override
public void issue(Byte byteObj, String assetHolderAddress, long cashNumber) {
System.out.println(String.format("issue(),bytes=%d,assetHolderAddress=%s,cashNumber=%d",byteObj.intValue(),assetHolderAddress,cashNumber));
}

@ContractEvent(name = "issue-asset-4")
@Override
public void issue(Byte byteObj, String assetHolderAddress, Bytes cashNumber) {
System.out.println(String.format("issue(),bytes=%d,assetHolderAddress=%s,cashNumber=%s",byteObj.intValue(),assetHolderAddress,cashNumber.toString()));
System.out.println("current LedgerHash="+eventContext.getCurrentLedgerHash().toBase58());
// 查询当前值;
KVDataEntry[] kvEntries = eventContext.getLedger().getDataEntries(eventContext.getCurrentLedgerHash(), assetHolderAddress, KEY_TOTAL);
// 计算资产的发行总数;
KVDataObject curTotal = (KVDataObject) kvEntries[0];
System.out.println("currTotal version="+curTotal.getVersion()+",value="+curTotal.getValue().toString());
eventContext.getLedger().dataAccount(assetHolderAddress).set(KEY_TOTAL, 100,curTotal.getVersion());
}

/*
* (non-Javadoc)
*
* @see
* com.jd.blockchain.contract.model.EventProcessingAwire#beforeEvent(com.jd.
* blockchain.contract.model.ContractEventContext)
*/
@Override
public void beforeEvent(ContractEventContext eventContext) {
this.eventContext = eventContext;
}

/*
* (non-Javadoc)
*
* @see com.jd.blockchain.contract.model.EventProcessingAwire#postEvent(com.jd.
* blockchain.contract.model.ContractEventContext,
* com.jd.blockchain.contract.model.ContractError)
*/
@Override
public void postEvent(ContractEventContext eventContext, ContractException error) {
this.eventContext = null;
}

@Override
public void postEvent(ContractException error) {

}

@Override
public void postEvent() {

}
}

+ 24
- 0
source/contract/contract-maven-plugin/src/test/resources/project-to-test/pom.xml View File

@@ -0,0 +1,24 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>com.jd.blockchain</groupId>
<artifactId>project-to-test</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>Test MyMojo</name>

<build>
<plugins>
<plugin>
<artifactId>contract-maven-plugin</artifactId>
<configuration>
<!--<outputDirectory>target/test-harness/project-to-test</outputDirectory>-->
<!-- The defined stubs -->
<project implementation="com.jd.blockchain.ledger.MyProjectStub"/>
<finalName>contract1</finalName>
</configuration>
</plugin>
</plugins>
</build>
</project>

BIN
source/contract/contract-maven-plugin/src/test/resources/project-to-test/target/contract.jar View File


+ 14
- 0
source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ContractArgs.java View File

@@ -0,0 +1,14 @@
package com.jd.blockchain.ledger;
import com.jd.blockchain.binaryproto.DataContract;
import com.jd.blockchain.consts.DataCodes;

import java.lang.reflect.Method;

/**
* contract's args;
*/
@DataContract(code = DataCodes.CONTRACT_ARGS)
public interface ContractArgs {
Method getMethod();
Object[] getArgs();
}

+ 2
- 2
source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/DataAccountKVSetOperationBuilderImpl.java View File

@@ -32,10 +32,10 @@ public class DataAccountKVSetOperationBuilderImpl implements DataAccountKVSetOpe
public DataAccountKVSetOperationBuilder set(String key, String value, long expVersion) {
BytesValue bytesValue;
if (JSONSerializeUtils.isJSON(value)) {
bytesValue = new BytesValueEntry(BytesValueType.JSON, value.getBytes());
bytesValue = new BytesValueEntry(BytesValueType.JSON, BytesUtils.toBytes(value));
}
else {
bytesValue = new BytesValueEntry(BytesValueType.TEXT, value.getBytes());
bytesValue = new BytesValueEntry(BytesValueType.TEXT, BytesUtils.toBytes(value));
}
operation.set(key, bytesValue, expVersion);
return this;


+ 22
- 0
source/sdk/sdk-samples/src/test/java/test/com/jd/blockchain/sdk/test/SDK_Contract_Test.java View File

@@ -18,10 +18,12 @@ import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.ClassPathResource;
import org.springframework.util.ReflectionUtils;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.lang.reflect.Method;

import static org.junit.Assert.*;

@@ -351,4 +353,24 @@ public class SDK_Contract_Test {
ContractBizContent actualObj = BinaryProtocol.decodeAs(bizBytes,ContractBizContent.class);
assertArrayEquals(contractBizContent.getAttrs(),actualObj.getAttrs());
}

@Test
public void testContractArgs(){
ContractBizContent contractBizContent = () -> new String[]{"param1"};
Method method = ReflectionUtils.findMethod(AssetContract2.class,"issue",ContractBizContent.class,String.class);
ContractArgs contractArgs = new ContractArgs() {
@Override
public Method getMethod() {
return method;
}

@Override
public Object[] getArgs() {
return new Object[]{contractBizContent,"hello"};
}
};

//add the annotation;

}
}

Loading…
Cancel
Save