@@ -7,15 +7,21 @@ public final class ClassicAlgorithm { | |||
public static final CryptoAlgorithm ED25519 = CryptoAlgorithmDefinition.defineSignature("ED25519", false, | |||
(byte) 21); | |||
public static final CryptoAlgorithm ECDSA = CryptoAlgorithmDefinition.defineSignature("ECDSA", false, (byte) 22); | |||
public static final CryptoAlgorithm RSA = CryptoAlgorithmDefinition.defineSignature("RSA", true, (byte) 23); | |||
public static final CryptoAlgorithm ECDSA = CryptoAlgorithmDefinition.defineSignature("ECDSA", false, | |||
(byte) 22); | |||
public static final CryptoAlgorithm SHA256 = CryptoAlgorithmDefinition.defineHash("SHA256", (byte) 24); | |||
public static final CryptoAlgorithm RSA = CryptoAlgorithmDefinition.defineSignature("RSA", true, | |||
(byte) 23); | |||
public static final CryptoAlgorithm RIPEMD160 = CryptoAlgorithmDefinition.defineHash("RIPEMD160", (byte) 25); | |||
public static final CryptoAlgorithm SHA256 = CryptoAlgorithmDefinition.defineHash("SHA256", | |||
(byte) 24); | |||
public static final CryptoAlgorithm AES = CryptoAlgorithmDefinition.defineSymmetricEncryption("AES", (byte) 26); | |||
public static final CryptoAlgorithm RIPEMD160 = CryptoAlgorithmDefinition.defineHash("RIPEMD160", | |||
(byte) 25); | |||
public static final CryptoAlgorithm AES = CryptoAlgorithmDefinition.defineSymmetricEncryption("AES", | |||
(byte) 26); | |||
public static final CryptoAlgorithm JVM_SECURE_RANDOM = CryptoAlgorithmDefinition.defineRandom("JVM-SECURE-RANDOM", | |||
(byte) 27); | |||
@@ -0,0 +1,18 @@ | |||
package test.com.jd.blockchain.crypto.service.classic; | |||
import com.jd.blockchain.utils.Bytes; | |||
import com.jd.blockchain.utils.codec.HexUtils; | |||
import org.junit.Assert; | |||
import org.junit.Test; | |||
public class EncodeTest { | |||
@Test | |||
public void test() { | |||
String pubKey = "7VeRLdGtSz1Y91gjLTqEdnkotzUfaAqdap3xw6fQ1yKHkvVq"; | |||
Bytes bytes = Bytes.fromBase58(pubKey); | |||
String hexString = HexUtils.encode(bytes.toBytes()); | |||
String code = hexString.substring(2, 4); | |||
Assert.assertEquals(code, "15"); // 15为十六进制,对应十进制为21(ED25519) | |||
} | |||
} |
@@ -45,7 +45,7 @@ | |||
<dependency> | |||
<groupId>com.jd.blockchain</groupId> | |||
<artifactId>browser</artifactId> | |||
<artifactId>explorer</artifactId> | |||
</dependency> | |||
<dependency> | |||
@@ -78,6 +78,23 @@ | |||
<version>${commons-io.version}</version> | |||
</dependency> | |||
<dependency> | |||
<groupId>org.bitbucket.mstrobel</groupId> | |||
<artifactId>procyon-core</artifactId> | |||
</dependency> | |||
<dependency> | |||
<groupId>org.bitbucket.mstrobel</groupId> | |||
<artifactId>procyon-expressions</artifactId> | |||
</dependency> | |||
<dependency> | |||
<groupId>org.bitbucket.mstrobel</groupId> | |||
<artifactId>procyon-reflection</artifactId> | |||
</dependency> | |||
<dependency> | |||
<groupId>org.bitbucket.mstrobel</groupId> | |||
<artifactId>procyon-compilertools</artifactId> | |||
</dependency> | |||
<dependency> | |||
<groupId>org.springframework.boot</groupId> | |||
<artifactId>spring-boot-starter-web</artifactId> | |||
@@ -0,0 +1,249 @@ | |||
package com.jd.blockchain.gateway.decompiler.loads; | |||
import com.strobel.assembler.ir.ConstantPool; | |||
import com.strobel.assembler.metadata.Buffer; | |||
import com.strobel.assembler.metadata.ClasspathTypeLoader; | |||
import com.strobel.assembler.metadata.ITypeLoader; | |||
import com.strobel.core.StringUtilities; | |||
import com.strobel.core.VerifyArgument; | |||
import java.io.ByteArrayInputStream; | |||
import java.util.LinkedHashMap; | |||
import java.util.LinkedHashSet; | |||
import java.util.Map; | |||
import java.util.logging.Level; | |||
import java.util.logging.Logger; | |||
public class BytesTypeLoader implements ITypeLoader { | |||
private final static Logger LOG = Logger.getLogger(BytesTypeLoader.class.getSimpleName()); | |||
private final ITypeLoader defaultTypeLoader; | |||
private final Map<String, LinkedHashSet<byte[]>> packageLocations; | |||
private final Map<String, byte[]> knownBytes; | |||
private String name; | |||
public BytesTypeLoader(byte[] bytes) { | |||
this(new ClasspathTypeLoader(), bytes); | |||
} | |||
public BytesTypeLoader(final ITypeLoader defaultTypeLoader, byte[] bytes) { | |||
this.defaultTypeLoader = VerifyArgument.notNull(defaultTypeLoader, "defaultTypeLoader"); | |||
this.packageLocations = new LinkedHashMap<>(); | |||
this.knownBytes = new LinkedHashMap<>(); | |||
Buffer innerNameBuffer = new Buffer(); | |||
if (tryLoadTypeFromBytes(bytes, innerNameBuffer)) { | |||
this.name = getInternalNameFromClassFile(innerNameBuffer); | |||
this.knownBytes.put(this.name, bytes); | |||
} else { | |||
throw new IllegalStateException("Input Class Bytes Exception !!!"); | |||
} | |||
} | |||
@Override | |||
public boolean tryLoadType(final String typeNameOrPath, final Buffer buffer) { | |||
VerifyArgument.notNull(typeNameOrPath, "typeNameOrPath"); | |||
VerifyArgument.notNull(buffer, "buffer"); | |||
if (LOG.isLoggable(Level.FINE)) { | |||
LOG.fine("Attempting to load type: " + typeNameOrPath + "..."); | |||
} | |||
final boolean hasExtension = StringUtilities.endsWithIgnoreCase(typeNameOrPath, ".class"); | |||
if (hasExtension) { | |||
return false; | |||
} | |||
String internalName = typeNameOrPath; | |||
if (tryLoadTypeFromName(internalName, buffer)) { | |||
return true; | |||
} | |||
for (int lastDelimiter = internalName.lastIndexOf('/'); | |||
lastDelimiter != -1; | |||
lastDelimiter = internalName.lastIndexOf('/')) { | |||
internalName = internalName.substring(0, lastDelimiter) + "$" + | |||
internalName.substring(lastDelimiter + 1); | |||
if (tryLoadTypeFromName(internalName, buffer)) { | |||
return true; | |||
} | |||
} | |||
if (LOG.isLoggable(Level.FINER)) { | |||
LOG.finer("Failed to load type: " + typeNameOrPath + "."); | |||
} | |||
return false; | |||
} | |||
private boolean tryLoadTypeFromName(final String internalName, final Buffer buffer) { | |||
if (tryLoadFromKnownLocation(internalName, buffer)) { | |||
return true; | |||
} | |||
if (defaultTypeLoader.tryLoadType(internalName, buffer)) { | |||
return true; | |||
} | |||
return false; | |||
} | |||
private boolean tryLoadFromKnownLocation(final String internalName, final Buffer buffer) { | |||
final byte[] knownFile = knownBytes.get(internalName); | |||
if (tryLoadBytes(knownFile, buffer)) { | |||
return true; | |||
} | |||
final int packageEnd = internalName.lastIndexOf('/'); | |||
String head; | |||
String tail; | |||
if (packageEnd < 0 || packageEnd >= internalName.length()) { | |||
head = StringUtilities.EMPTY; | |||
tail = internalName; | |||
} | |||
else { | |||
head = internalName.substring(0, packageEnd); | |||
tail = internalName.substring(packageEnd + 1); | |||
} | |||
while (true) { | |||
final LinkedHashSet<byte[]> directories = packageLocations.get(head); | |||
if (directories != null) { | |||
for (final byte[] directory : directories) { | |||
if (tryLoadBytes(internalName, directory, buffer, true)) { | |||
return true; | |||
} | |||
} | |||
} | |||
final int split = head.lastIndexOf('/'); | |||
if (split <= 0) { | |||
break; | |||
} | |||
tail = head.substring(split + 1) + '/' + tail; | |||
head = head.substring(0, split); | |||
} | |||
return false; | |||
} | |||
private boolean tryLoadBytes(final byte[] bytes, final Buffer buffer) { | |||
if (bytes == null || bytes.length == 0) { | |||
return false; | |||
} | |||
int length = bytes.length; | |||
buffer.position(0); | |||
buffer.reset(length); | |||
new ByteArrayInputStream(bytes).read(buffer.array(), 0, length); | |||
buffer.position(0); | |||
return true; | |||
} | |||
private boolean tryLoadBytes(final String internalName, final byte[] bytes, final Buffer buffer, final boolean trustName) { | |||
if (!tryLoadBytes(bytes, buffer)) { | |||
return false; | |||
} | |||
final String actualName = getInternalNameFromClassFile(buffer); | |||
final String name = trustName ? (internalName != null ? internalName : actualName) | |||
: actualName; | |||
if (name == null) { | |||
return false; | |||
} | |||
final boolean nameMatches = StringUtilities.equals(actualName, internalName); | |||
final boolean result = internalName == null || nameMatches; | |||
if (result) { | |||
final int packageEnd = name.lastIndexOf('/'); | |||
final String packageName; | |||
if (packageEnd < 0 || packageEnd >= name.length()) { | |||
packageName = StringUtilities.EMPTY; | |||
} | |||
else { | |||
packageName = name.substring(0, packageEnd); | |||
} | |||
registerKnownPath(packageName, bytes); | |||
knownBytes.put(actualName, bytes); | |||
} | |||
else { | |||
buffer.reset(0); | |||
} | |||
return result; | |||
} | |||
private void registerKnownPath(final String packageName, final byte[] directory) { | |||
if (directory == null || directory.length == 0) { | |||
return; | |||
} | |||
LinkedHashSet<byte[]> directories = packageLocations.get(packageName); | |||
if (directories == null) { | |||
packageLocations.put(packageName, directories = new LinkedHashSet<>()); | |||
} | |||
if (!directories.add(directory)) { | |||
return; | |||
} | |||
} | |||
private static String getInternalNameFromClassFile(final Buffer b) { | |||
final long magic = b.readInt() & 0xFFFFFFFFL; | |||
if (magic != 0xCAFEBABEL) { | |||
return null; | |||
} | |||
b.readUnsignedShort(); // minor version | |||
b.readUnsignedShort(); // major version | |||
final ConstantPool constantPool = ConstantPool.read(b); | |||
b.readUnsignedShort(); // access flags | |||
final ConstantPool.TypeInfoEntry thisClass = constantPool.getEntry(b.readUnsignedShort()); | |||
b.position(0); | |||
return thisClass.getName(); | |||
} | |||
public String getName() { | |||
return name; | |||
} | |||
private boolean tryLoadTypeFromBytes(byte[] bytes, Buffer buffer) { | |||
if (bytes == null || bytes.length == 0 || buffer == null) { | |||
return false; | |||
} | |||
int length = bytes.length; | |||
buffer.position(0); | |||
buffer.reset(length); | |||
new ByteArrayInputStream(bytes).read(buffer.array(), 0, length); | |||
buffer.position(0); | |||
return true; | |||
} | |||
} |
@@ -0,0 +1,218 @@ | |||
package com.jd.blockchain.gateway.decompiler.utils; | |||
import com.jd.blockchain.gateway.decompiler.loads.BytesTypeLoader; | |||
import com.strobel.assembler.metadata.JarTypeLoader; | |||
import com.strobel.decompiler.Decompiler; | |||
import com.strobel.decompiler.DecompilerSettings; | |||
import com.strobel.decompiler.PlainTextOutput; | |||
import org.apache.commons.io.FileUtils; | |||
import org.apache.commons.io.IOUtils; | |||
import java.io.File; | |||
import java.io.IOException; | |||
import java.io.InputStream; | |||
import java.io.StringWriter; | |||
import java.net.URL; | |||
import java.util.Arrays; | |||
import java.util.List; | |||
import java.util.concurrent.atomic.AtomicLong; | |||
import java.util.jar.JarFile; | |||
public class DecompilerUtils { | |||
public static final AtomicLong SAVE_INDEX = new AtomicLong(); | |||
public static final String MANIFEST_MF = "/META-INF/MANIFEST.MF"; | |||
public static final String MAIN_CLASS = "Main-Class"; | |||
public static String SAVE_DIR = null; | |||
static { | |||
init(); | |||
} | |||
private static void init() { | |||
try { | |||
URL url = DecompilerUtils.class | |||
.getProtectionDomain() | |||
.getCodeSource() | |||
.getLocation(); | |||
String currPath = java.net.URLDecoder.decode(url.getPath(), "UTF-8"); | |||
if (currPath.contains("!/")) { | |||
currPath = currPath.substring(5, currPath.indexOf("!/")); | |||
} | |||
if (currPath.endsWith(".jar")) { | |||
currPath = currPath.substring(0, currPath.lastIndexOf("/") + 1); | |||
} | |||
File file = new File(currPath); | |||
String homeDir = file.getParent(); | |||
SAVE_DIR = homeDir + File.separator + "temp"; | |||
File dir = new File(SAVE_DIR); | |||
if (!dir.exists()) { | |||
dir.mkdir(); | |||
} | |||
} catch (Exception e) { | |||
throw new IllegalStateException(e); | |||
} | |||
} | |||
public static String decompile(String classPath) { | |||
String decompileJava; | |||
try (StringWriter stringWriter = new StringWriter()) { | |||
final DecompilerSettings settings = DecompilerSettings.javaDefaults(); | |||
Decompiler.decompile( | |||
classPath, | |||
new PlainTextOutput(stringWriter), | |||
settings | |||
); | |||
decompileJava = stringWriter.toString(); | |||
} catch (final Exception e) { | |||
throw new IllegalStateException(e); | |||
} | |||
return decompileJava; | |||
} | |||
public static List<String> readManifest2Array(final String jarFilePath, final String charSet) { | |||
String manifest = readManifest(jarFilePath, charSet); | |||
String[] manifests = manifest.split("\r\n"); | |||
return Arrays.asList(manifests); | |||
} | |||
public static String readManifest(final String jarFilePath, final String charSet) { | |||
return decompileJarFile(jarFilePath, MANIFEST_MF, false, charSet); | |||
} | |||
public static String decompileMainClassFromBytes(byte[] bytes) { | |||
try { | |||
String jarFile = writeBytes(bytes, SAVE_DIR, "jar"); | |||
String decompileJava = decompileMainClassFromJarFile(jarFile); | |||
// 然后删除jarFile文件 | |||
FileUtils.forceDelete(new File(jarFile)); | |||
return decompileJava; | |||
} catch (Exception e) { | |||
throw new IllegalStateException(e); | |||
} | |||
} | |||
public static String decompileMainClassFromJarFile(final String jarFilePath) { | |||
// 首先获取Main-Class | |||
List<String> manifests = readManifest2Array(jarFilePath, null); | |||
if (manifests == null || manifests.size() == 0) { | |||
throw new IllegalStateException("MANIFEST.MF not Exist or is Empty !!!"); | |||
} else { | |||
String mainClass = null; | |||
for (String s : manifests) { | |||
String inner = s.trim().replaceAll(" ", ""); | |||
if (inner.startsWith(MAIN_CLASS)) { | |||
mainClass = inner.split(":")[1]; | |||
break; | |||
} | |||
} | |||
if (mainClass == null || mainClass.length() == 0) { | |||
throw new IllegalStateException("MANIFEST.MF has not Main-Class !!!"); | |||
} | |||
// 然后读取MainClass中的内容并进行反编译 | |||
String classPath = mainClass.replaceAll("\\.", "/"); | |||
return decompileJarFile(jarFilePath, classPath, true, null); | |||
} | |||
} | |||
public static String decompileJarFile(final String jarFilePath, final String source, final boolean isClass, final String charSet) { | |||
// 对于Class文件和非Class文件处理方式不同 | |||
if (!isClass) { | |||
// 非Class文件不需要编译,直接从文件中读取即可 | |||
String innerSource = source; | |||
if (!innerSource.startsWith("/")) { | |||
innerSource = "/" + innerSource; | |||
} | |||
try { | |||
URL jarUrl = new URL("jar:file:" + jarFilePath + "!" + innerSource); | |||
InputStream inputStream = jarUrl.openStream(); | |||
byte[] bytes = IOUtils.toByteArray(inputStream); | |||
if (charSet == null) { | |||
return new String(bytes); | |||
} | |||
return new String(bytes, charSet); | |||
} catch (Exception e) { | |||
throw new IllegalStateException(e); | |||
} | |||
} else { | |||
String decompileJava; | |||
try (StringWriter stringWriter = new StringWriter()) { | |||
JarFile jarFile = new JarFile(jarFilePath); | |||
JarTypeLoader jarTypeLoader = new JarTypeLoader(jarFile); | |||
final DecompilerSettings settings = DecompilerSettings.javaDefaults(); | |||
settings.setTypeLoader(jarTypeLoader); | |||
Decompiler.decompile( | |||
source, | |||
new PlainTextOutput(stringWriter), | |||
settings | |||
); | |||
decompileJava = stringWriter.toString(); | |||
} catch (final Exception e) { | |||
throw new IllegalStateException(e); | |||
} | |||
return decompileJava; | |||
} | |||
} | |||
public static String decompile(byte[] classBytes) { | |||
String decompileJava; | |||
try (StringWriter stringWriter = new StringWriter()) { | |||
BytesTypeLoader bytesTypeLoader = new BytesTypeLoader(classBytes); | |||
String name = bytesTypeLoader.getName(); | |||
final DecompilerSettings settings = DecompilerSettings.javaDefaults(); | |||
settings.setTypeLoader(bytesTypeLoader); | |||
Decompiler.decompile( | |||
name, | |||
new PlainTextOutput(stringWriter), | |||
settings | |||
); | |||
decompileJava = stringWriter.toString(); | |||
} catch (final Exception e) { | |||
throw new IllegalStateException(e); | |||
} | |||
return decompileJava; | |||
} | |||
public static String decompile(InputStream in) { | |||
try { | |||
return decompile(IOUtils.toByteArray(in)); | |||
} catch (final Exception e) { | |||
throw new IllegalStateException(e); | |||
} | |||
} | |||
public static byte[] read2Bytes(String filePath) throws IOException { | |||
return FileUtils.readFileToByteArray(new File(filePath)); | |||
} | |||
public static String writeBytes(byte[] bytes, String directory, String suffix) throws IOException { | |||
String saveFileName = System.currentTimeMillis() + "-" + SAVE_INDEX.incrementAndGet() + "." + suffix; | |||
File saveFile = new File(directory + File.separator + saveFileName); | |||
FileUtils.writeByteArrayToFile(saveFile, bytes); | |||
return saveFile.getPath(); | |||
} | |||
} |
@@ -2,7 +2,9 @@ package com.jd.blockchain.gateway.service; | |||
import com.jd.blockchain.crypto.HashDigest; | |||
import com.jd.blockchain.ledger.ParticipantNode; | |||
import com.jd.blockchain.sdk.ContractSettings; | |||
import com.jd.blockchain.sdk.LedgerInitSettings; | |||
import com.jd.blockchain.utils.Bytes; | |||
/** | |||
* queryService only for gateway; | |||
@@ -34,4 +36,15 @@ public interface GatewayQueryService { | |||
* @return | |||
*/ | |||
LedgerInitSettings getLedgerInitSettings(HashDigest ledgerHash); | |||
/** | |||
* 获取账本指定合约信息 | |||
* | |||
* @param ledgerHash | |||
* 账本Hash | |||
* @param address | |||
* 合约地址 | |||
* @return | |||
*/ | |||
ContractSettings getContractSettings(HashDigest ledgerHash, String address); | |||
} |
@@ -7,8 +7,11 @@ import com.jd.blockchain.consensus.bftsmart.BftsmartConsensusProvider; | |||
import com.jd.blockchain.consensus.mq.MsgQueueConsensusProvider; | |||
import com.jd.blockchain.crypto.HashDigest; | |||
import com.jd.blockchain.gateway.PeerService; | |||
import com.jd.blockchain.gateway.decompiler.utils.DecompilerUtils; | |||
import com.jd.blockchain.ledger.ContractInfo; | |||
import com.jd.blockchain.ledger.LedgerMetadata; | |||
import com.jd.blockchain.ledger.ParticipantNode; | |||
import com.jd.blockchain.sdk.ContractSettings; | |||
import com.jd.blockchain.sdk.LedgerInitSettings; | |||
import com.jd.blockchain.utils.QueryUtil; | |||
import com.jd.blockchain.utils.codec.HexUtils; | |||
@@ -53,6 +56,21 @@ public class GatewayQueryServiceHandler implements GatewayQueryService { | |||
return initLedgerInitSettings(participantNodes, ledgerMetadata); | |||
} | |||
@Override | |||
public ContractSettings getContractSettings(HashDigest ledgerHash, String address) { | |||
ContractInfo contractInfo = peerService.getQueryService().getContract(ledgerHash, address); | |||
return contractSettings(contractInfo); | |||
} | |||
private ContractSettings contractSettings(ContractInfo contractInfo) { | |||
ContractSettings contractSettings = new ContractSettings(contractInfo.getAddress(), contractInfo.getPubKey(), contractInfo.getRootHash()); | |||
byte[] chainCodeBytes = contractInfo.getChainCode(); | |||
// 将反编译chainCode | |||
String mainClassJava = DecompilerUtils.decompileMainClassFromBytes(chainCodeBytes); | |||
contractSettings.setChainCode(mainClassJava); | |||
return contractSettings; | |||
} | |||
/** | |||
* 初始化账本配置 | |||
* | |||
@@ -8,6 +8,7 @@ import com.jd.blockchain.gateway.service.DataRetrievalService; | |||
import com.jd.blockchain.gateway.service.GatewayQueryService; | |||
import com.jd.blockchain.ledger.*; | |||
import com.jd.blockchain.sdk.BlockchainExtendQueryService; | |||
import com.jd.blockchain.sdk.ContractSettings; | |||
import com.jd.blockchain.sdk.LedgerInitSettings; | |||
import com.jd.blockchain.tools.keygen.KeyGenCommand; | |||
import com.jd.blockchain.utils.BaseConstant; | |||
@@ -23,6 +24,7 @@ import java.util.List; | |||
@RestController | |||
@RequestMapping(path = "/") | |||
public class BlockBrowserController implements BlockchainExtendQueryService { | |||
private static org.slf4j.Logger LOGGER = LoggerFactory.getLogger(BlockBrowserController.class); | |||
@Autowired | |||
@@ -263,10 +265,15 @@ public class BlockBrowserController implements BlockchainExtendQueryService { | |||
} | |||
@RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/contracts/address/{address}") | |||
public ContractSettings getContractSettings(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, | |||
@PathVariable(name = "address") String address) { | |||
return gatewayQueryService.getContractSettings(ledgerHash, address); | |||
} | |||
// @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/contracts/address/{address}") | |||
@Override | |||
public AccountHeader getContract(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, | |||
@PathVariable(name = "address") String address) { | |||
return peerService.getQueryService().getContract(ledgerHash, address); | |||
public ContractInfo getContract(HashDigest ledgerHash, String address) { | |||
return peerService.getQueryService().getContract(ledgerHash, address); | |||
} | |||
@RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/blocks/latest") | |||
@@ -450,7 +457,8 @@ public class BlockBrowserController implements BlockchainExtendQueryService { | |||
} | |||
@RequestMapping(method = RequestMethod.GET, value = "ledgers/{ledgerHash}/**/search") | |||
public Object dataRetrieval(@PathVariable(name = "ledgerHash") HashDigest ledgerHash,HttpServletRequest request) { | |||
public Object dataRetrieval(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, | |||
HttpServletRequest request) { | |||
String result; | |||
if (dataRetrievalUrl == null || dataRetrievalUrl.length() <= 0) { | |||
result = "{'message':'OK','data':'" + "data.retrieval.url is empty" + "'}"; | |||
@@ -5,9 +5,10 @@ import com.jd.blockchain.crypto.PubKey; | |||
import com.jd.blockchain.ledger.AccountHeader; | |||
import com.jd.blockchain.ledger.BytesValue; | |||
import com.jd.blockchain.ledger.BytesData; | |||
import com.jd.blockchain.ledger.ContractInfo; | |||
import com.jd.blockchain.utils.Bytes; | |||
public class ContractAccount implements AccountHeader { | |||
public class ContractAccount implements ContractInfo { | |||
private static final Bytes CONTRACT_INFO_PREFIX = Bytes.fromString("INFO" + LedgerConsts.KEY_SEPERATOR); | |||
@@ -5,19 +5,7 @@ import java.util.List; | |||
import com.jd.blockchain.contract.ContractException; | |||
import com.jd.blockchain.crypto.HashDigest; | |||
import com.jd.blockchain.ledger.AccountHeader; | |||
import com.jd.blockchain.ledger.BytesValue; | |||
import com.jd.blockchain.ledger.KVDataEntry; | |||
import com.jd.blockchain.ledger.KVDataObject; | |||
import com.jd.blockchain.ledger.KVDataVO; | |||
import com.jd.blockchain.ledger.KVInfoVO; | |||
import com.jd.blockchain.ledger.LedgerBlock; | |||
import com.jd.blockchain.ledger.LedgerInfo; | |||
import com.jd.blockchain.ledger.LedgerMetadata; | |||
import com.jd.blockchain.ledger.LedgerTransaction; | |||
import com.jd.blockchain.ledger.ParticipantNode; | |||
import com.jd.blockchain.ledger.TransactionState; | |||
import com.jd.blockchain.ledger.UserInfo; | |||
import com.jd.blockchain.ledger.*; | |||
import com.jd.blockchain.ledger.core.ContractAccountSet; | |||
import com.jd.blockchain.ledger.core.DataAccount; | |||
import com.jd.blockchain.ledger.core.DataAccountSet; | |||
@@ -367,7 +355,7 @@ public class LedgerQueryService implements BlockchainQueryService { | |||
} | |||
@Override | |||
public AccountHeader getContract(HashDigest ledgerHash, String address) { | |||
public ContractInfo getContract(HashDigest ledgerHash, String address) { | |||
LedgerRepository ledger = ledgerService.getLedger(ledgerHash); | |||
LedgerBlock block = ledger.getLatestBlock(); | |||
ContractAccountSet contractAccountSet = ledger.getContractAccountSet(block); | |||
@@ -5,23 +5,7 @@ import java.util.List; | |||
import com.jd.blockchain.contract.LedgerContext; | |||
import com.jd.blockchain.crypto.HashDigest; | |||
import com.jd.blockchain.ledger.AccountHeader; | |||
import com.jd.blockchain.ledger.BlockchainIdentity; | |||
import com.jd.blockchain.ledger.BytesValue; | |||
import com.jd.blockchain.ledger.BytesData; | |||
import com.jd.blockchain.ledger.DataAccountKVSetOperation; | |||
import com.jd.blockchain.ledger.DataAccountRegisterOperation; | |||
import com.jd.blockchain.ledger.KVDataEntry; | |||
import com.jd.blockchain.ledger.KVInfoVO; | |||
import com.jd.blockchain.ledger.LedgerBlock; | |||
import com.jd.blockchain.ledger.LedgerInfo; | |||
import com.jd.blockchain.ledger.LedgerMetadata; | |||
import com.jd.blockchain.ledger.LedgerTransaction; | |||
import com.jd.blockchain.ledger.Operation; | |||
import com.jd.blockchain.ledger.ParticipantNode; | |||
import com.jd.blockchain.ledger.TransactionState; | |||
import com.jd.blockchain.ledger.UserInfo; | |||
import com.jd.blockchain.ledger.UserRegisterOperation; | |||
import com.jd.blockchain.ledger.*; | |||
import com.jd.blockchain.ledger.core.impl.OperationHandleContext; | |||
import com.jd.blockchain.transaction.BlockchainQueryService; | |||
import com.jd.blockchain.transaction.DataAccountKVSetOperationBuilder; | |||
@@ -186,7 +170,7 @@ public class ContractLedgerContext implements LedgerContext { | |||
} | |||
@Override | |||
public AccountHeader getContract(HashDigest ledgerHash, String address) { | |||
public ContractInfo getContract(HashDigest ledgerHash, String address) { | |||
return innerQueryService.getContract(ledgerHash, address); | |||
} | |||
@@ -0,0 +1,13 @@ | |||
package com.jd.blockchain.ledger; | |||
import com.jd.blockchain.binaryproto.DataContract; | |||
import com.jd.blockchain.binaryproto.DataField; | |||
import com.jd.blockchain.binaryproto.PrimitiveType; | |||
import com.jd.blockchain.consts.DataCodes; | |||
@DataContract(code= DataCodes.CONTRACT) | |||
public interface ContractInfo extends AccountHeader { | |||
@DataField(order=4, primitiveType= PrimitiveType.BYTES) | |||
byte[] getChainCode(); | |||
} |
@@ -296,7 +296,7 @@ public interface BlockchainQueryService { | |||
* @param address | |||
* @return | |||
*/ | |||
AccountHeader getContract(HashDigest ledgerHash, String address); | |||
ContractInfo getContract(HashDigest ledgerHash, String address); | |||
/** | |||
* get users by ledgerHash and its range; | |||
@@ -11,7 +11,8 @@ abstract class OperationResultHolder implements OperationResultHandle { | |||
private volatile boolean completed; | |||
private EventMulticaster<OperationCompletedListener> listenerMulticaster; | |||
private EventMulticaster<OperationCompletedListener> listenerMulticaster = | |||
new EventMulticaster<>(OperationCompletedListener.class); | |||
/** | |||
* 导致结束的错误; | |||
@@ -3,6 +3,7 @@ package com.jd.blockchain.peer.web; | |||
import java.util.ArrayList; | |||
import java.util.List; | |||
import com.jd.blockchain.ledger.*; | |||
import org.springframework.beans.factory.annotation.Autowired; | |||
import org.springframework.web.bind.annotation.PathVariable; | |||
import org.springframework.web.bind.annotation.RequestBody; | |||
@@ -13,19 +14,6 @@ import org.springframework.web.bind.annotation.RestController; | |||
import com.jd.blockchain.contract.ContractException; | |||
import com.jd.blockchain.crypto.HashDigest; | |||
import com.jd.blockchain.ledger.AccountHeader; | |||
import com.jd.blockchain.ledger.BytesValue; | |||
import com.jd.blockchain.ledger.KVDataEntry; | |||
import com.jd.blockchain.ledger.KVDataObject; | |||
import com.jd.blockchain.ledger.KVDataVO; | |||
import com.jd.blockchain.ledger.KVInfoVO; | |||
import com.jd.blockchain.ledger.LedgerBlock; | |||
import com.jd.blockchain.ledger.LedgerInfo; | |||
import com.jd.blockchain.ledger.LedgerMetadata; | |||
import com.jd.blockchain.ledger.LedgerTransaction; | |||
import com.jd.blockchain.ledger.ParticipantNode; | |||
import com.jd.blockchain.ledger.TransactionState; | |||
import com.jd.blockchain.ledger.UserInfo; | |||
import com.jd.blockchain.ledger.core.ContractAccountSet; | |||
import com.jd.blockchain.ledger.core.DataAccount; | |||
import com.jd.blockchain.ledger.core.DataAccountSet; | |||
@@ -454,8 +442,8 @@ public class LedgerQueryController implements BlockchainQueryService { | |||
@RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/contracts/address/{address}") | |||
@Override | |||
public AccountHeader getContract(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, | |||
@PathVariable(name = "address") String address) { | |||
public ContractInfo getContract(@PathVariable(name = "ledgerHash") HashDigest ledgerHash, | |||
@PathVariable(name = "address") String address) { | |||
LedgerRepository ledger = ledgerService.getLedger(ledgerHash); | |||
LedgerBlock block = ledger.getLatestBlock(); | |||
ContractAccountSet contractAccountSet = ledger.getContractAccountSet(block); | |||
@@ -41,7 +41,7 @@ | |||
<properties> | |||
<my.utils.version>0.8.1-SNAPSHOT</my.utils.version> | |||
<bft-smart.version>0.0.8.RELEASE</bft-smart.version> | |||
<browser.version>0.6.6.RELEASE</browser.version> | |||
<explorer.version>0.7.0.RELEASE</explorer.version> | |||
<!-- <spring.framework.version>4.3.4.RELEASE</spring.framework.version> --> | |||
<!-- <spring.mongo.version>1.9.3.RELEASE</spring.mongo.version> <spring.dao.version>2.0.8</spring.dao.version> | |||
<spring.security.version>4.2.0.RELEASE</spring.security.version> --> | |||
@@ -49,7 +49,7 @@ | |||
<shiro.version>1.2.2</shiro.version> | |||
<aspectj.version>1.8.8</aspectj.version> | |||
<!-- <asm.version>5.2</asm.version> --> | |||
<procyon.version>0.5.35</procyon.version> | |||
<druid.version>1.0.18</druid.version> | |||
<commons.fileupload.version>1.2.2</commons.fileupload.version> | |||
<mybatis.spring.version>1.2.4</mybatis.spring.version> | |||
@@ -112,8 +112,8 @@ | |||
<dependency> | |||
<groupId>com.jd.blockchain</groupId> | |||
<artifactId>browser</artifactId> | |||
<version>${browser.version}</version> | |||
<artifactId>explorer</artifactId> | |||
<version>${explorer.version}</version> | |||
</dependency> | |||
<!-- The test dependency --> | |||
@@ -147,6 +147,27 @@ | |||
<version>${disruptor.version}</version> | |||
</dependency> | |||
<dependency> | |||
<groupId>org.bitbucket.mstrobel</groupId> | |||
<artifactId>procyon-core</artifactId> | |||
<version>${procyon.version}</version> | |||
</dependency> | |||
<dependency> | |||
<groupId>org.bitbucket.mstrobel</groupId> | |||
<artifactId>procyon-expressions</artifactId> | |||
<version>${procyon.version}</version> | |||
</dependency> | |||
<dependency> | |||
<groupId>org.bitbucket.mstrobel</groupId> | |||
<artifactId>procyon-reflection</artifactId> | |||
<version>${procyon.version}</version> | |||
</dependency> | |||
<dependency> | |||
<groupId>org.bitbucket.mstrobel</groupId> | |||
<artifactId>procyon-compilertools</artifactId> | |||
<version>${procyon.version}</version> | |||
</dependency> | |||
<dependency> | |||
<groupId>com.alibaba</groupId> | |||
<artifactId>fastjson</artifactId> | |||
@@ -0,0 +1,64 @@ | |||
package com.jd.blockchain.sdk; | |||
import com.jd.blockchain.crypto.HashDigest; | |||
import com.jd.blockchain.crypto.PubKey; | |||
import com.jd.blockchain.utils.Bytes; | |||
public class ContractSettings { | |||
private Bytes address; | |||
private PubKey pubKey; | |||
private HashDigest rootHash; | |||
private String chainCode; | |||
public ContractSettings() { | |||
} | |||
public ContractSettings(Bytes address, PubKey pubKey, HashDigest rootHash) { | |||
this.address = address; | |||
this.pubKey = pubKey; | |||
this.rootHash = rootHash; | |||
} | |||
public ContractSettings(Bytes address, PubKey pubKey, HashDigest rootHash, String chainCode) { | |||
this.address = address; | |||
this.pubKey = pubKey; | |||
this.rootHash = rootHash; | |||
this.chainCode = chainCode; | |||
} | |||
public Bytes getAddress() { | |||
return address; | |||
} | |||
public void setAddress(Bytes address) { | |||
this.address = address; | |||
} | |||
public PubKey getPubKey() { | |||
return pubKey; | |||
} | |||
public void setPubKey(PubKey pubKey) { | |||
this.pubKey = pubKey; | |||
} | |||
public HashDigest getRootHash() { | |||
return rootHash; | |||
} | |||
public void setRootHash(HashDigest rootHash) { | |||
this.rootHash = rootHash; | |||
} | |||
public String getChainCode() { | |||
return chainCode; | |||
} | |||
public void setChainCode(String chainCode) { | |||
this.chainCode = chainCode; | |||
} | |||
} |
@@ -167,7 +167,7 @@ public abstract class BlockchainServiceProxy implements BlockchainService { | |||
} | |||
@Override | |||
public AccountHeader getContract(HashDigest ledgerHash, String address) { | |||
public ContractInfo getContract(HashDigest ledgerHash, String address) { | |||
return getQueryService(ledgerHash).getContract(ledgerHash, address); | |||
} | |||
@@ -544,7 +544,7 @@ public interface HttpBlockchainQueryService extends BlockchainExtendQueryService | |||
*/ | |||
@HttpAction(method=HttpMethod.GET, path="ledgers/{ledgerHash}/contracts/address/{address}") | |||
@Override | |||
AccountHeader getContract(@PathParam(name="ledgerHash", converter=HashDigestToStringConverter.class) HashDigest ledgerHash, | |||
ContractInfo getContract(@PathParam(name="ledgerHash", converter=HashDigestToStringConverter.class) HashDigest ledgerHash, | |||
@PathParam(name="address") String address); | |||
@@ -373,7 +373,7 @@ public class MockerNodeContext implements BlockchainQueryService { | |||
} | |||
@Override | |||
public AccountHeader getContract(HashDigest ledgerHash, String address) { | |||
public ContractInfo getContract(HashDigest ledgerHash, String address) { | |||
return queryService.getContract(ledgerHash, address); | |||
} | |||