@@ -7,15 +7,21 @@ public final class ClassicAlgorithm { | |||||
public static final CryptoAlgorithm ED25519 = CryptoAlgorithmDefinition.defineSignature("ED25519", false, | public static final CryptoAlgorithm ED25519 = CryptoAlgorithmDefinition.defineSignature("ED25519", false, | ||||
(byte) 21); | (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", | public static final CryptoAlgorithm JVM_SECURE_RANDOM = CryptoAlgorithmDefinition.defineRandom("JVM-SECURE-RANDOM", | ||||
(byte) 27); | (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> | <dependency> | ||||
<groupId>com.jd.blockchain</groupId> | <groupId>com.jd.blockchain</groupId> | ||||
<artifactId>browser</artifactId> | |||||
<artifactId>explorer</artifactId> | |||||
</dependency> | </dependency> | ||||
<dependency> | <dependency> | ||||
@@ -78,6 +78,23 @@ | |||||
<version>${commons-io.version}</version> | <version>${commons-io.version}</version> | ||||
</dependency> | </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> | <dependency> | ||||
<groupId>org.springframework.boot</groupId> | <groupId>org.springframework.boot</groupId> | ||||
<artifactId>spring-boot-starter-web</artifactId> | <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.crypto.HashDigest; | ||||
import com.jd.blockchain.ledger.ParticipantNode; | import com.jd.blockchain.ledger.ParticipantNode; | ||||
import com.jd.blockchain.sdk.ContractSettings; | |||||
import com.jd.blockchain.sdk.LedgerInitSettings; | import com.jd.blockchain.sdk.LedgerInitSettings; | ||||
import com.jd.blockchain.utils.Bytes; | |||||
/** | /** | ||||
* queryService only for gateway; | * queryService only for gateway; | ||||
@@ -34,4 +36,15 @@ public interface GatewayQueryService { | |||||
* @return | * @return | ||||
*/ | */ | ||||
LedgerInitSettings getLedgerInitSettings(HashDigest ledgerHash); | 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.consensus.mq.MsgQueueConsensusProvider; | ||||
import com.jd.blockchain.crypto.HashDigest; | import com.jd.blockchain.crypto.HashDigest; | ||||
import com.jd.blockchain.gateway.PeerService; | 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.LedgerMetadata; | ||||
import com.jd.blockchain.ledger.ParticipantNode; | import com.jd.blockchain.ledger.ParticipantNode; | ||||
import com.jd.blockchain.sdk.ContractSettings; | |||||
import com.jd.blockchain.sdk.LedgerInitSettings; | import com.jd.blockchain.sdk.LedgerInitSettings; | ||||
import com.jd.blockchain.utils.QueryUtil; | import com.jd.blockchain.utils.QueryUtil; | ||||
import com.jd.blockchain.utils.codec.HexUtils; | import com.jd.blockchain.utils.codec.HexUtils; | ||||
@@ -53,6 +56,21 @@ public class GatewayQueryServiceHandler implements GatewayQueryService { | |||||
return initLedgerInitSettings(participantNodes, ledgerMetadata); | 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.gateway.service.GatewayQueryService; | ||||
import com.jd.blockchain.ledger.*; | import com.jd.blockchain.ledger.*; | ||||
import com.jd.blockchain.sdk.BlockchainExtendQueryService; | import com.jd.blockchain.sdk.BlockchainExtendQueryService; | ||||
import com.jd.blockchain.sdk.ContractSettings; | |||||
import com.jd.blockchain.sdk.LedgerInitSettings; | import com.jd.blockchain.sdk.LedgerInitSettings; | ||||
import com.jd.blockchain.tools.keygen.KeyGenCommand; | import com.jd.blockchain.tools.keygen.KeyGenCommand; | ||||
import com.jd.blockchain.utils.BaseConstant; | import com.jd.blockchain.utils.BaseConstant; | ||||
@@ -23,6 +24,7 @@ import java.util.List; | |||||
@RestController | @RestController | ||||
@RequestMapping(path = "/") | @RequestMapping(path = "/") | ||||
public class BlockBrowserController implements BlockchainExtendQueryService { | public class BlockBrowserController implements BlockchainExtendQueryService { | ||||
private static org.slf4j.Logger LOGGER = LoggerFactory.getLogger(BlockBrowserController.class); | private static org.slf4j.Logger LOGGER = LoggerFactory.getLogger(BlockBrowserController.class); | ||||
@Autowired | @Autowired | ||||
@@ -263,10 +265,15 @@ public class BlockBrowserController implements BlockchainExtendQueryService { | |||||
} | } | ||||
@RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/contracts/address/{address}") | @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 | @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") | @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") | @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; | String result; | ||||
if (dataRetrievalUrl == null || dataRetrievalUrl.length() <= 0) { | if (dataRetrievalUrl == null || dataRetrievalUrl.length() <= 0) { | ||||
result = "{'message':'OK','data':'" + "data.retrieval.url is empty" + "'}"; | 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.AccountHeader; | ||||
import com.jd.blockchain.ledger.BytesValue; | import com.jd.blockchain.ledger.BytesValue; | ||||
import com.jd.blockchain.ledger.BytesData; | import com.jd.blockchain.ledger.BytesData; | ||||
import com.jd.blockchain.ledger.ContractInfo; | |||||
import com.jd.blockchain.utils.Bytes; | 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); | 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.contract.ContractException; | ||||
import com.jd.blockchain.crypto.HashDigest; | 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.ContractAccountSet; | ||||
import com.jd.blockchain.ledger.core.DataAccount; | import com.jd.blockchain.ledger.core.DataAccount; | ||||
import com.jd.blockchain.ledger.core.DataAccountSet; | import com.jd.blockchain.ledger.core.DataAccountSet; | ||||
@@ -367,7 +355,7 @@ public class LedgerQueryService implements BlockchainQueryService { | |||||
} | } | ||||
@Override | @Override | ||||
public AccountHeader getContract(HashDigest ledgerHash, String address) { | |||||
public ContractInfo getContract(HashDigest ledgerHash, String address) { | |||||
LedgerRepository ledger = ledgerService.getLedger(ledgerHash); | LedgerRepository ledger = ledgerService.getLedger(ledgerHash); | ||||
LedgerBlock block = ledger.getLatestBlock(); | LedgerBlock block = ledger.getLatestBlock(); | ||||
ContractAccountSet contractAccountSet = ledger.getContractAccountSet(block); | ContractAccountSet contractAccountSet = ledger.getContractAccountSet(block); | ||||
@@ -5,23 +5,7 @@ import java.util.List; | |||||
import com.jd.blockchain.contract.LedgerContext; | import com.jd.blockchain.contract.LedgerContext; | ||||
import com.jd.blockchain.crypto.HashDigest; | 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.ledger.core.impl.OperationHandleContext; | ||||
import com.jd.blockchain.transaction.BlockchainQueryService; | import com.jd.blockchain.transaction.BlockchainQueryService; | ||||
import com.jd.blockchain.transaction.DataAccountKVSetOperationBuilder; | import com.jd.blockchain.transaction.DataAccountKVSetOperationBuilder; | ||||
@@ -186,7 +170,7 @@ public class ContractLedgerContext implements LedgerContext { | |||||
} | } | ||||
@Override | @Override | ||||
public AccountHeader getContract(HashDigest ledgerHash, String address) { | |||||
public ContractInfo getContract(HashDigest ledgerHash, String address) { | |||||
return innerQueryService.getContract(ledgerHash, 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 | * @param address | ||||
* @return | * @return | ||||
*/ | */ | ||||
AccountHeader getContract(HashDigest ledgerHash, String address); | |||||
ContractInfo getContract(HashDigest ledgerHash, String address); | |||||
/** | /** | ||||
* get users by ledgerHash and its range; | * get users by ledgerHash and its range; | ||||
@@ -11,7 +11,8 @@ abstract class OperationResultHolder implements OperationResultHandle { | |||||
private volatile boolean completed; | 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.ArrayList; | ||||
import java.util.List; | import java.util.List; | ||||
import com.jd.blockchain.ledger.*; | |||||
import org.springframework.beans.factory.annotation.Autowired; | import org.springframework.beans.factory.annotation.Autowired; | ||||
import org.springframework.web.bind.annotation.PathVariable; | import org.springframework.web.bind.annotation.PathVariable; | ||||
import org.springframework.web.bind.annotation.RequestBody; | 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.contract.ContractException; | ||||
import com.jd.blockchain.crypto.HashDigest; | 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.ContractAccountSet; | ||||
import com.jd.blockchain.ledger.core.DataAccount; | import com.jd.blockchain.ledger.core.DataAccount; | ||||
import com.jd.blockchain.ledger.core.DataAccountSet; | 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}") | @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/contracts/address/{address}") | ||||
@Override | @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); | LedgerRepository ledger = ledgerService.getLedger(ledgerHash); | ||||
LedgerBlock block = ledger.getLatestBlock(); | LedgerBlock block = ledger.getLatestBlock(); | ||||
ContractAccountSet contractAccountSet = ledger.getContractAccountSet(block); | ContractAccountSet contractAccountSet = ledger.getContractAccountSet(block); | ||||
@@ -41,7 +41,7 @@ | |||||
<properties> | <properties> | ||||
<my.utils.version>0.8.1-SNAPSHOT</my.utils.version> | <my.utils.version>0.8.1-SNAPSHOT</my.utils.version> | ||||
<bft-smart.version>0.0.8.RELEASE</bft-smart.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.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.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> --> | <spring.security.version>4.2.0.RELEASE</spring.security.version> --> | ||||
@@ -49,7 +49,7 @@ | |||||
<shiro.version>1.2.2</shiro.version> | <shiro.version>1.2.2</shiro.version> | ||||
<aspectj.version>1.8.8</aspectj.version> | <aspectj.version>1.8.8</aspectj.version> | ||||
<!-- <asm.version>5.2</asm.version> --> | <!-- <asm.version>5.2</asm.version> --> | ||||
<procyon.version>0.5.35</procyon.version> | |||||
<druid.version>1.0.18</druid.version> | <druid.version>1.0.18</druid.version> | ||||
<commons.fileupload.version>1.2.2</commons.fileupload.version> | <commons.fileupload.version>1.2.2</commons.fileupload.version> | ||||
<mybatis.spring.version>1.2.4</mybatis.spring.version> | <mybatis.spring.version>1.2.4</mybatis.spring.version> | ||||
@@ -112,8 +112,8 @@ | |||||
<dependency> | <dependency> | ||||
<groupId>com.jd.blockchain</groupId> | <groupId>com.jd.blockchain</groupId> | ||||
<artifactId>browser</artifactId> | |||||
<version>${browser.version}</version> | |||||
<artifactId>explorer</artifactId> | |||||
<version>${explorer.version}</version> | |||||
</dependency> | </dependency> | ||||
<!-- The test dependency --> | <!-- The test dependency --> | ||||
@@ -147,6 +147,27 @@ | |||||
<version>${disruptor.version}</version> | <version>${disruptor.version}</version> | ||||
</dependency> | </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> | <dependency> | ||||
<groupId>com.alibaba</groupId> | <groupId>com.alibaba</groupId> | ||||
<artifactId>fastjson</artifactId> | <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 | @Override | ||||
public AccountHeader getContract(HashDigest ledgerHash, String address) { | |||||
public ContractInfo getContract(HashDigest ledgerHash, String address) { | |||||
return getQueryService(ledgerHash).getContract(ledgerHash, 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}") | @HttpAction(method=HttpMethod.GET, path="ledgers/{ledgerHash}/contracts/address/{address}") | ||||
@Override | @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); | @PathParam(name="address") String address); | ||||
@@ -373,7 +373,7 @@ public class MockerNodeContext implements BlockchainQueryService { | |||||
} | } | ||||
@Override | @Override | ||||
public AccountHeader getContract(HashDigest ledgerHash, String address) { | |||||
public ContractInfo getContract(HashDigest ledgerHash, String address) { | |||||
return queryService.getContract(ledgerHash, address); | return queryService.getContract(ledgerHash, address); | ||||
} | } | ||||