@@ -52,9 +52,17 @@ public class BinaryProtocol { | |||
public static <T> T decodeAs(byte[] dataSegment, Class<T> contractType) { | |||
return decodeAs(dataSegment, contractType, true); | |||
} | |||
public static <T> T decodeAs(byte[] dataSegment, Class<T> contractType, boolean autoRegister) { | |||
DataContractEncoder encoder = DataContractContext.ENCODER_LOOKUP.lookup(contractType); | |||
if (encoder == null) { | |||
throw new DataContractException("Contract type is not registered! --" + contractType.toString()); | |||
if (autoRegister) { | |||
encoder = DataContractContext.resolve(contractType); | |||
}else { | |||
throw new DataContractException("Contract type is not registered! --" + contractType.toString()); | |||
} | |||
} | |||
BytesSlice bytes = new BytesSlice(dataSegment, 0, dataSegment.length); | |||
return encoder.decode(bytes.getInputStream()); | |||
@@ -1,16 +1,10 @@ | |||
package com.jd.blockchain.transaction; | |||
import java.io.IOException; | |||
import java.util.Arrays; | |||
import java.util.Collection; | |||
import java.util.Comparator; | |||
import org.springframework.cglib.proxy.UndeclaredThrowableException; | |||
import com.jd.blockchain.crypto.AsymmetricKeypair; | |||
import com.jd.blockchain.crypto.HashDigest; | |||
import com.jd.blockchain.ledger.DigitalSignature; | |||
import com.jd.blockchain.ledger.OperationResult; | |||
import com.jd.blockchain.ledger.PreparedTransaction; | |||
import com.jd.blockchain.ledger.TransactionContent; | |||
import com.jd.blockchain.ledger.TransactionRequest; | |||
@@ -21,34 +15,17 @@ public class PreparedTx implements PreparedTransaction { | |||
private TransactionRequestBuilder txReqBuilder; | |||
private TransactionService txProcessor; | |||
private OperationResultHandle[] opReturnValueHandlers; | |||
private TxStateManager stateManager; | |||
private TransactionService txService; | |||
/** | |||
* 创建一个“就绪交易”对象; | |||
* | |||
* @param txReqBuilder 交易请求构建器; | |||
* @param txProcessor 交易处理服务; | |||
* @param opReturnValueHandlerList 操作返回值处理器列表; | |||
* @param txReqBuilder 交易请求构建器; | |||
* @param txService 交易处理服务; | |||
*/ | |||
public PreparedTx(TxStateManager stateManager, TransactionRequestBuilder txReqBuilder, | |||
TransactionService txProcessor, Collection<OperationResultHandle> opReturnValueHandlerList) { | |||
this.stateManager = stateManager; | |||
public PreparedTx(TransactionRequestBuilder txReqBuilder, TransactionService txService) { | |||
this.txReqBuilder = txReqBuilder; | |||
this.txProcessor = txProcessor; | |||
this.opReturnValueHandlers = opReturnValueHandlerList | |||
.toArray(new OperationResultHandle[opReturnValueHandlerList.size()]); | |||
// 按照操作索引升序排列; | |||
Arrays.sort(opReturnValueHandlers, new Comparator<OperationResultHandle>() { | |||
@Override | |||
public int compare(OperationResultHandle o1, OperationResultHandle o2) { | |||
return o1.getOperationIndex() - o2.getOperationIndex(); | |||
} | |||
}); | |||
this.txService = txService; | |||
} | |||
@Override | |||
@@ -75,60 +52,14 @@ public class PreparedTx implements PreparedTransaction { | |||
@Override | |||
public TransactionResponse commit() { | |||
stateManager.commit(); | |||
TransactionResponse txResponse = null; | |||
try { | |||
TransactionRequest txReq = txReqBuilder.buildRequest(); | |||
// 发起交易请求; | |||
txResponse = txProcessor.process(txReq); | |||
stateManager.complete(); | |||
} catch (Exception ex) { | |||
stateManager.close(); | |||
handleError(ex); | |||
throw new UndeclaredThrowableException(ex); | |||
} | |||
if (txResponse != null) { | |||
handleResults(txResponse); | |||
} | |||
return txResponse; | |||
// 生成请求; | |||
TransactionRequest txReq = txReqBuilder.buildRequest(); | |||
// 发起交易请求; | |||
return txService.process(txReq); | |||
} | |||
@Override | |||
public void close() throws IOException { | |||
if (!stateManager.close()) { | |||
TransactionCancelledExeption error = new TransactionCancelledExeption( | |||
"Prepared transaction has been cancelled!"); | |||
handleError(error); | |||
} | |||
} | |||
private void handleError(Throwable error) { | |||
for (OperationResultHandle handle : opReturnValueHandlers) { | |||
handle.complete(error); | |||
} | |||
} | |||
private void handleResults(TransactionResponse txResponse) { | |||
// 解析返回值;正常的情况下,返回结果列表与结果处理器列表中元素对应的操作索引是一致的; | |||
OperationResult[] opResults = txResponse.getOperationResults(); | |||
if (opResults != null && opResults.length > 0) { | |||
if (opResults.length != opReturnValueHandlers.length) { | |||
throw new IllegalStateException(String.format( | |||
"The operation result list of tx doesn't match it's return value handler list! --[TX.Content.Hash=%s][NumOfResults=%s][NumOfHandlers=%s]", | |||
txResponse.getContentHash(), opResults.length, opReturnValueHandlers.length)); | |||
} | |||
for (int i = 0; i < opResults.length; i++) { | |||
if (opResults[i].getIndex() != opReturnValueHandlers[i].getOperationIndex()) { | |||
throw new IllegalStateException( | |||
"The operation indexes of the items in the result list and in the handler list don't match!"); | |||
} | |||
opReturnValueHandlers[i].complete(opResults[i].getResult()); | |||
} | |||
} | |||
} | |||
} |
@@ -0,0 +1,108 @@ | |||
package com.jd.blockchain.transaction; | |||
import java.io.IOException; | |||
import java.util.Arrays; | |||
import java.util.Collection; | |||
import java.util.Comparator; | |||
import org.springframework.cglib.proxy.UndeclaredThrowableException; | |||
import com.jd.blockchain.crypto.AsymmetricKeypair; | |||
import com.jd.blockchain.ledger.DigitalSignature; | |||
import com.jd.blockchain.ledger.OperationResult; | |||
import com.jd.blockchain.ledger.TransactionRequestBuilder; | |||
import com.jd.blockchain.ledger.TransactionResponse; | |||
class StatefulPreparedTx extends PreparedTx { | |||
private OperationResultHandle[] opReturnValueHandlers; | |||
private TxStateManager stateManager; | |||
/** | |||
* 创建一个“就绪交易”对象; | |||
* | |||
* @param txReqBuilder 交易请求构建器; | |||
* @param txProcessor 交易处理服务; | |||
* @param opReturnValueHandlerList 操作返回值处理器列表; | |||
*/ | |||
StatefulPreparedTx(TxStateManager stateManager, TransactionRequestBuilder txReqBuilder, | |||
TransactionService txProcessor, Collection<OperationResultHandle> opReturnValueHandlerList) { | |||
super(txReqBuilder, txProcessor); | |||
this.stateManager = stateManager; | |||
this.opReturnValueHandlers = opReturnValueHandlerList | |||
.toArray(new OperationResultHandle[opReturnValueHandlerList.size()]); | |||
// 按照操作索引升序排列; | |||
Arrays.sort(opReturnValueHandlers, new Comparator<OperationResultHandle>() { | |||
@Override | |||
public int compare(OperationResultHandle o1, OperationResultHandle o2) { | |||
return o1.getOperationIndex() - o2.getOperationIndex(); | |||
} | |||
}); | |||
} | |||
@Override | |||
public DigitalSignature sign(AsymmetricKeypair keyPair) { | |||
DigitalSignature signature = SignatureUtils.sign(getTransactionContent(), keyPair); | |||
addSignature(signature); | |||
return signature; | |||
} | |||
@Override | |||
public TransactionResponse commit() { | |||
stateManager.commit(); | |||
TransactionResponse txResponse = null; | |||
try { | |||
// 发起交易请求; | |||
txResponse = super.commit(); | |||
stateManager.complete(); | |||
} catch (Exception ex) { | |||
stateManager.close(); | |||
handleError(ex); | |||
throw new UndeclaredThrowableException(ex); | |||
} | |||
if (txResponse != null) { | |||
handleResults(txResponse); | |||
} | |||
return txResponse; | |||
} | |||
@Override | |||
public void close() throws IOException { | |||
if (!stateManager.close()) { | |||
TransactionCancelledExeption error = new TransactionCancelledExeption( | |||
"Prepared transaction has been cancelled!"); | |||
handleError(error); | |||
} | |||
} | |||
private void handleError(Throwable error) { | |||
for (OperationResultHandle handle : opReturnValueHandlers) { | |||
handle.complete(error); | |||
} | |||
} | |||
private void handleResults(TransactionResponse txResponse) { | |||
// 解析返回值;正常的情况下,返回结果列表与结果处理器列表中元素对应的操作索引是一致的; | |||
OperationResult[] opResults = txResponse.getOperationResults(); | |||
if (opResults != null && opResults.length > 0) { | |||
if (opResults.length != opReturnValueHandlers.length) { | |||
throw new IllegalStateException(String.format( | |||
"The operation result list of tx doesn't match it's return value handler list! --[TX.Content.Hash=%s][NumOfResults=%s][NumOfHandlers=%s]", | |||
txResponse.getContentHash(), opResults.length, opReturnValueHandlers.length)); | |||
} | |||
for (int i = 0; i < opResults.length; i++) { | |||
if (opResults[i].getIndex() != opReturnValueHandlers[i].getOperationIndex()) { | |||
throw new IllegalStateException( | |||
"The operation indexes of the items in the result list and in the handler list don't match!"); | |||
} | |||
opReturnValueHandlers[i].complete(opResults[i].getResult()); | |||
} | |||
} | |||
} | |||
} |
@@ -32,7 +32,7 @@ public class TxTemplate implements TransactionTemplate { | |||
public PreparedTransaction prepare() { | |||
stateManager.prepare(); | |||
TransactionRequestBuilder txReqBuilder = txBuilder.prepareRequest(); | |||
return new PreparedTx(stateManager, txReqBuilder, txService, txBuilder.getReturnValuehandlers()); | |||
return new StatefulPreparedTx(stateManager, txReqBuilder, txService, txBuilder.getReturnValuehandlers()); | |||
} | |||
@Override | |||
@@ -1,6 +1,8 @@ | |||
package com.jd.blockchain.sdk; | |||
import com.jd.blockchain.crypto.HashDigest; | |||
import com.jd.blockchain.ledger.PreparedTransaction; | |||
import com.jd.blockchain.ledger.TransactionContent; | |||
import com.jd.blockchain.ledger.TransactionTemplate; | |||
public interface BlockchainTransactionService { | |||
@@ -12,6 +14,14 @@ public interface BlockchainTransactionService { | |||
*/ | |||
TransactionTemplate newTransaction(HashDigest ledgerHash); | |||
/** | |||
* 根据交易内容准备交易实例; | |||
* | |||
* @param content | |||
* @return | |||
*/ | |||
PreparedTransaction prepareTransaction(TransactionContent content); | |||
// /** | |||
// * 以指定的科目和流水号发起新交易; | |||
// * | |||
@@ -11,6 +11,8 @@ 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.PreparedTransaction; | |||
import com.jd.blockchain.ledger.TransactionContent; | |||
import com.jd.blockchain.ledger.TransactionState; | |||
import com.jd.blockchain.ledger.TransactionTemplate; | |||
import com.jd.blockchain.ledger.UserInfo; | |||
@@ -19,7 +21,9 @@ import com.jd.blockchain.sdk.BlockchainEventListener; | |||
import com.jd.blockchain.sdk.BlockchainService; | |||
import com.jd.blockchain.sdk.converters.ClientResolveUtil; | |||
import com.jd.blockchain.transaction.BlockchainQueryService; | |||
import com.jd.blockchain.transaction.PreparedTx; | |||
import com.jd.blockchain.transaction.TransactionService; | |||
import com.jd.blockchain.transaction.TxRequestBuilder; | |||
import com.jd.blockchain.transaction.TxTemplate; | |||
public abstract class BlockchainServiceProxy implements BlockchainService { | |||
@@ -33,6 +37,12 @@ public abstract class BlockchainServiceProxy implements BlockchainService { | |||
public TransactionTemplate newTransaction(HashDigest ledgerHash) { | |||
return new TxTemplate(ledgerHash, getTransactionService(ledgerHash)); | |||
} | |||
@Override | |||
public PreparedTransaction prepareTransaction(TransactionContent content) { | |||
TxRequestBuilder txReqBuilder = new TxRequestBuilder(content); | |||
return new PreparedTx(txReqBuilder, getTransactionService(content.getLedgerHash())); | |||
} | |||
@Override | |||
public BlockchainEventHandle addBlockchainEventListener(int filteredEventTypes, String filteredTxHash, | |||
@@ -0,0 +1,96 @@ | |||
/** | |||
* Copyright: Copyright 2016-2020 JD.COM All Right Reserved | |||
* FileName: com.jd.blockchain.sdk.samples.SDKDemo_RegisterUser | |||
* Author: shaozhuguang | |||
* Department: 区块链研发部 | |||
* Date: 2018/10/18 下午2:00 | |||
* Description: 注册用户 | |||
*/ | |||
package com.jd.blockchain.sdk.samples; | |||
import com.jd.blockchain.binaryproto.BinaryProtocol; | |||
import com.jd.blockchain.binaryproto.DataContractRegistry; | |||
import com.jd.blockchain.crypto.AsymmetricKeypair; | |||
import com.jd.blockchain.crypto.HashDigest; | |||
import com.jd.blockchain.crypto.PrivKey; | |||
import com.jd.blockchain.crypto.PubKey; | |||
import com.jd.blockchain.ledger.*; | |||
import com.jd.blockchain.sdk.BlockchainService; | |||
import com.jd.blockchain.sdk.client.GatewayServiceFactory; | |||
import com.jd.blockchain.utils.ConsoleUtils; | |||
/** | |||
* 注册用户 | |||
* | |||
* @author shaozhuguang | |||
* @create 2018/10/18 | |||
* @since 1.0.0 | |||
*/ | |||
public class SDKDemo_Tx_Persistance { | |||
public static void main(String[] args) { | |||
String GATEWAY_IPADDR = "127.0.0.1"; | |||
int GATEWAY_PORT = 8081; | |||
if (args != null && args.length == 2) { | |||
GATEWAY_IPADDR = args[0]; | |||
GATEWAY_PORT = Integer.parseInt(args[1]); | |||
} | |||
// 注册相关class | |||
DataContractRegistry.register(TransactionContent.class); | |||
DataContractRegistry.register(TransactionContentBody.class); | |||
DataContractRegistry.register(TransactionRequest.class); | |||
DataContractRegistry.register(NodeRequest.class); | |||
DataContractRegistry.register(EndpointRequest.class); | |||
DataContractRegistry.register(TransactionResponse.class); | |||
PrivKey privKey = SDKDemo_Params.privkey1; | |||
PubKey pubKey = SDKDemo_Params.pubKey1; | |||
BlockchainKeypair CLIENT_CERT = new BlockchainKeypair(SDKDemo_Params.pubKey0, SDKDemo_Params.privkey0); | |||
boolean SECURE = false; | |||
GatewayServiceFactory gatewayServiceFactory = GatewayServiceFactory.connect(GATEWAY_IPADDR, GATEWAY_PORT, SECURE, | |||
CLIENT_CERT); | |||
BlockchainService blockchainService = gatewayServiceFactory.getBlockchainService(); | |||
HashDigest[] ledgerHashs = blockchainService.getLedgerHashs(); | |||
// 在本地定义注册账号的 TX; | |||
TransactionTemplate txTemp = blockchainService.newTransaction(ledgerHashs[0]); | |||
// existed signer | |||
AsymmetricKeypair keyPair = new BlockchainKeypair(pubKey, privKey); | |||
BlockchainKeypair user = BlockchainKeyGenerator.getInstance().generate(); | |||
// 注册 | |||
txTemp.users().register(user.getIdentity()); | |||
// 定义角色权限; | |||
txTemp.security().roles().configure("MANAGER") | |||
.enable(LedgerPermission.REGISTER_USER, LedgerPermission.REGISTER_DATA_ACCOUNT) | |||
.enable(TransactionPermission.CONTRACT_OPERATION); | |||
txTemp.security().authorziations().forUser(user.getIdentity()).authorize("MANAGER"); | |||
// TX 准备就绪; | |||
PreparedTransaction prepTx = txTemp.prepare(); | |||
// 序列化交易内容; | |||
byte[] txContentBytes = BinaryProtocol.encode(prepTx.getTransactionContent(), TransactionContent.class); | |||
// 反序列化交易内容; | |||
TransactionContent txContent = BinaryProtocol.decodeAs(txContentBytes, TransactionContent.class); | |||
// 根据交易内容重新准备交易; | |||
PreparedTransaction decodedPrepTx = blockchainService.prepareTransaction(txContent); | |||
// 使用私钥进行签名; | |||
decodedPrepTx.sign(keyPair); | |||
// 提交交易; | |||
TransactionResponse transactionResponse = decodedPrepTx.commit(); | |||
ConsoleUtils.info("register user complete, result is [%s]", transactionResponse.isSuccess()); | |||
} | |||
} |