Browse Source

Completed new feature that re-prepare transaction from bytes;

tags/1.1.4
huanghaiquan 5 years ago
parent
commit
2ac5d5cca6
7 changed files with 243 additions and 80 deletions
  1. +9
    -1
      source/binary-proto/src/main/java/com/jd/blockchain/binaryproto/BinaryProtocol.java
  2. +9
    -78
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/PreparedTx.java
  3. +108
    -0
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/StatefulPreparedTx.java
  4. +1
    -1
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/TxTemplate.java
  5. +10
    -0
      source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/BlockchainTransactionService.java
  6. +10
    -0
      source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/proxy/BlockchainServiceProxy.java
  7. +96
    -0
      source/sdk/sdk-samples/src/main/java/com/jd/blockchain/sdk/samples/SDKDemo_Tx_Persistance.java

+ 9
- 1
source/binary-proto/src/main/java/com/jd/blockchain/binaryproto/BinaryProtocol.java View File

@@ -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());


+ 9
- 78
source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/PreparedTx.java View File

@@ -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());
}
}
}

}

+ 108
- 0
source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/StatefulPreparedTx.java View File

@@ -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());
}
}
}

}

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

@@ -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


+ 10
- 0
source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/BlockchainTransactionService.java View File

@@ -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);

// /**
// * 以指定的科目和流水号发起新交易;
// *


+ 10
- 0
source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/proxy/BlockchainServiceProxy.java View File

@@ -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,


+ 96
- 0
source/sdk/sdk-samples/src/main/java/com/jd/blockchain/sdk/samples/SDKDemo_Tx_Persistance.java View File

@@ -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());
}
}

Loading…
Cancel
Save