com.jd.blockchain.sdk.service.PeerBlockchainServiceFactory Maven / Gradle / Ivy
package com.jd.blockchain.sdk.service;
import com.jd.blockchain.consensus.*;
import com.jd.blockchain.consensus.client.ClientFactory;
import com.jd.blockchain.consensus.client.ClientSettings;
import com.jd.blockchain.consensus.client.ConsensusClient;
import com.jd.blockchain.crypto.asymmetric.CryptoKeyPair;
import com.jd.blockchain.crypto.hash.HashDigest;
import com.jd.blockchain.ledger.CryptoSetting;
import com.jd.blockchain.ledger.data.TransactionService;
import com.jd.blockchain.manage.GatewayIncomingSetting;
import com.jd.blockchain.manage.LedgerIncomingSetting;
import com.jd.blockchain.sdk.*;
import com.jd.blockchain.sdk.proxy.HttpBlockchainQueryService;
import com.jd.blockchain.utils.http.agent.HttpServiceAgent;
import com.jd.blockchain.utils.http.agent.ServiceConnection;
import com.jd.blockchain.utils.http.agent.ServiceConnectionManager;
import com.jd.blockchain.utils.http.agent.ServiceEndpoint;
import com.jd.blockchain.utils.io.ByteArray;
import com.jd.blockchain.utils.net.NetworkAddress;
import com.jd.blockchain.utils.security.AuthenticationException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.Closeable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class PeerBlockchainServiceFactory implements BlockchainServiceFactory, Closeable {
private static Logger LOGGER = LoggerFactory.getLogger(PeerBlockchainServiceFactory.class);
private static final Map peerBlockchainServiceFactories = new ConcurrentHashMap<>();
private static final Map peerManageServices = new ConcurrentHashMap<>();
private static final Map accessContextMap = new ConcurrentHashMap<>();
private ServiceConnectionManager httpConnectionManager;
private PeerServiceProxy peerServiceProxy;
/**
* @param httpConnectionManager
* Http请求管理器;
* @param accessAbleLedgers
* 可用账本列表;
*/
protected PeerBlockchainServiceFactory(ServiceConnectionManager httpConnectionManager,
LedgerAccessContextImpl[] accessAbleLedgers) {
this.httpConnectionManager = httpConnectionManager;
this.peerServiceProxy = new PeerServiceProxy(accessAbleLedgers);
}
public void addLedgerAccessContexts(LedgerAccessContextImpl[] accessContexts) {
this.peerServiceProxy.addLedgerAccessContexts(accessContexts);
}
@Override
public BlockchainService getBlockchainService() {
return peerServiceProxy;
}
/**
* 返回交易服务;
*
*
*
* 返回的交易服务聚合了该节点绑定的多个账本的交易服务,并根据交易请求中指定的目标账本选择相应的交易服务进行转发;
*
* @return
*/
public TransactionService getTransactionService() {
return peerServiceProxy;
}
/**
* 连接到指定的共识节点;
*
* @param peerAddr
* 提供对网关接入认证的节点的认证地址列表;
* 按列表的先后顺序连接节点进行认证,从第一个成功通过的节点请求整个区块链网络的拓扑配置,并建立起和整个区块链网络的连接;
* 此参数指定的节点列表可以是整个区块链网络的全部节点的子集,而不必包含所有节点;
*
* @return 区块链服务工厂实例;
*/
public static PeerBlockchainServiceFactory connect(CryptoKeyPair gatewayKey, NetworkAddress peerAddr, List peerProviders) {
if (peerProviders == null || peerProviders.isEmpty()) {
throw new AuthenticationException("No peer Provider was set!");
}
ClientIdentificationsProvider authIdProvider = authIdProvider(gatewayKey, peerProviders);
GatewayIncomingSetting incomingSetting = auth(peerAddr, authIdProvider);
if (incomingSetting == null) {
throw new AuthenticationException("No peer was succeed authenticating from!");
}
PeerBlockchainServiceFactory factory = null;
ServiceConnectionManager httpConnectionManager;
PeerManageService peerManageService;
if (peerBlockchainServiceFactories.containsKey(peerAddr)) {
factory = peerBlockchainServiceFactories.get(peerAddr);
httpConnectionManager = factory.httpConnectionManager;
} else {
httpConnectionManager = new ServiceConnectionManager();
}
if (peerManageServices.containsKey(peerAddr)) {
peerManageService = peerManageServices.get(peerAddr);
} else {
ServiceConnection httpConnection = httpConnectionManager.create(new ServiceEndpoint(peerAddr));
peerManageService = new PeerManageService(httpConnection,
HttpServiceAgent.createService(HttpBlockchainQueryService.class,
httpConnection, null));
peerManageServices.put(peerAddr, peerManageService);
}
LedgerIncomingSetting[] ledgerSettings = incomingSetting.getLedgers();
// 判断当前节点对应账本是否一致
List needInitSettings = new ArrayList<>();
for (LedgerIncomingSetting setting : ledgerSettings) {
HashDigest currLedgerHash = setting.getLedgerHash();
if (!accessContextMap.containsKey(currLedgerHash)) {
needInitSettings.add(setting);
}
}
if (!needInitSettings.isEmpty()) {
LedgerAccessContextImpl[] accessAbleLedgers = new LedgerAccessContextImpl[needInitSettings.size()];
BlockchainQueryService queryService = peerManageService.getQueryService();
for (int i = 0; i < needInitSettings.size(); i++) {
LedgerIncomingSetting ledgerSetting = needInitSettings.get(i);
String providerName = ledgerSetting.getProviderName();
ConsensusProvider provider = ConsensusProviders.getProvider(providerName);
byte[] clientSettingBytes = ByteArray.fromBase64(ledgerSetting.getClientSetting());
ClientIncomingSettings clientIncomingSettings = provider.getSettingsFactory().getIncomingSettingsEncoder().decode(clientSettingBytes);
ClientFactory clientFactory = provider.getClientFactory();
ClientSettings clientSettings = clientFactory.buildClientSettings(clientIncomingSettings);
ConsensusClient consensusClient = clientFactory.setupClient(clientSettings);
TransactionService autoSigningTxProcService = enableGatewayAutoSigning(gatewayKey,
ledgerSetting.getCryptoSetting(), consensusClient);
LedgerAccessContextImpl accCtx = new LedgerAccessContextImpl();
accCtx.ledgerHash = ledgerSetting.getLedgerHash();
accCtx.cryptoSetting = ledgerSetting.getCryptoSetting();
accCtx.queryService = queryService;
accCtx.txProcService = autoSigningTxProcService;
accCtx.consensusClient = consensusClient;
accessAbleLedgers[i] = accCtx;
accessContextMap.put(accCtx.ledgerHash, accCtx);
}
if (factory == null) {
factory = new PeerBlockchainServiceFactory(httpConnectionManager,
accessAbleLedgers);
peerBlockchainServiceFactories.put(peerAddr, factory);
} else {
factory.addLedgerAccessContexts(accessAbleLedgers);
}
// PeerBlockchainServiceFactory factory = new PeerBlockchainServiceFactory(httpConnectionManager,
// accessAbleLedgers);
}
// ServiceConnectionManager httpConnectionManager = new ServiceConnectionManager();
// ServiceConnection httpConnection = httpConnectionManager.create(new ServiceEndpoint(peerAddr));
// BlockchainQueryService queryService = HttpServiceAgent.createService(HttpBlockchainQueryService.class,
// httpConnection, null);
//
// LedgerIncomingSetting[] ledgerSettings = incomingSetting.getLedgers();
//
// LedgerAccessContextImpl[] accessAbleLedgers = new LedgerAccessContextImpl[ledgerSettings.length];
// for (int i = 0; i < ledgerSettings.length; i++) {
// LedgerIncomingSetting ledgerSetting = ledgerSettings[i];
// String providerName = ledgerSetting.getProviderName();
// ConsensusProvider provider = ConsensusProviders.getProvider(providerName);
// byte[] clientSettingBytes = ByteArray.fromBase64(ledgerSetting.getClientSetting());
//
// ClientIncomingSettings clientIncomingSettings = provider.getSettingsFactory().getIncomingSettingsEncoder().decode(clientSettingBytes);
// ClientFactory clientFactory = provider.getClientFactory();
// ClientSettings clientSettings = clientFactory.buildClientSettings(clientIncomingSettings);
// ConsensusClient consensusClient = clientFactory.setupClient(clientSettings);
//
// TransactionService autoSigningTxProcService = enableGatewayAutoSigning(gatewayKey,
// ledgerSetting.getCryptoSetting(), consensusClient);
//
//
// LedgerAccessContextImpl accCtx = new LedgerAccessContextImpl();
// accCtx.ledgerHash = ledgerSetting.getLedgerHash();
// accCtx.cryptoSetting = ledgerSetting.getCryptoSetting();
// accCtx.queryService = queryService;
// accCtx.txProcService = autoSigningTxProcService;
// accCtx.consensusClient = consensusClient;
//
// accessAbleLedgers[i] = accCtx;
//
// accessContextMap.put(accCtx.ledgerHash, accCtx);
// }
//
// PeerBlockchainServiceFactory factory = new PeerBlockchainServiceFactory(httpConnectionManager,
// accessAbleLedgers);
return factory;
}
private static GatewayIncomingSetting auth(NetworkAddress peerAuthAddr, ClientIdentifications authIds) {
try {
ManagementHttpService gatewayMngService = getGatewayManageService(peerAuthAddr);
// 接入认证,获得接入配置;
// 传递网关账户地址及签名;
GatewayIncomingSetting incomingSetting = gatewayMngService.authenticateGateway(authIds);
return incomingSetting;
} catch (Exception e) {
LOGGER.warn("Cann't authenticate gateway incoming from peer[" + peerAuthAddr.toString() + "]!--"
+ e.getMessage(), e);
return null;
}
}
private static ManagementHttpService getGatewayManageService(NetworkAddress peer) {
ServiceEndpoint peerServer = new ServiceEndpoint(peer.getHost(), peer.getPort(), false);
ManagementHttpService gatewayMngService = HttpServiceAgent.createService(ManagementHttpService.class,
peerServer);
return gatewayMngService;
}
/**
* 启用网关自动签名;
*
* @param nodeKeyPair
* @param cryptoSetting
* @return
*/
private static TransactionService enableGatewayAutoSigning(CryptoKeyPair nodeKeyPair, CryptoSetting cryptoSetting,
ConsensusClient consensusClient) {
NodeSigningAppender signingAppender = new NodeSigningAppender(cryptoSetting.getHashAlgorithm(),
nodeKeyPair, consensusClient);
return signingAppender.init();
}
@Override
public void close() {
try {
for (Map.Entry entry : accessContextMap.entrySet()) {
LedgerAccessContextImpl ctx = entry.getValue();
ctx.consensusClient.close();
}
httpConnectionManager.close();
} catch (Exception e) {
throw new RuntimeException(e.getMessage(), e);
}
}
private static ClientIdentificationsProvider authIdProvider(CryptoKeyPair gatewayKey, List peerProviders) {
ClientIdentificationsProvider authIdProvider = new ClientIdentificationsProvider();
for (String peerProvider : peerProviders) {
ConsensusProvider provider = ConsensusProviders.getProvider(peerProvider);
ClientFactory clientFactory = provider.getClientFactory();
ClientIdentification authId = clientFactory.buildAuthId(gatewayKey);
authIdProvider.add(authId);
}
return authIdProvider;
}
private static class LedgerAccessContextImpl implements LedgerAccessContext {
private HashDigest ledgerHash;
private CryptoSetting cryptoSetting;
private TransactionService txProcService;
private BlockchainQueryService queryService;
private ConsensusClient consensusClient;
@Override
public HashDigest getLedgerHash() {
return ledgerHash;
}
@Override
public CryptoSetting getCryptoSetting() {
return cryptoSetting;
}
@Override
public TransactionService getTransactionService() {
return txProcService;
}
@Override
public BlockchainQueryService getQueryService() {
return queryService;
}
}
private static final class PeerManageService {
public PeerManageService(ServiceConnection httpConnection, BlockchainQueryService queryService) {
this.httpConnection = httpConnection;
this.queryService = queryService;
}
ServiceConnection httpConnection;
BlockchainQueryService queryService;
public ServiceConnection getHttpConnection() {
return httpConnection;
}
public void setHttpConnection(ServiceConnection httpConnection) {
this.httpConnection = httpConnection;
}
public BlockchainQueryService getQueryService() {
return queryService;
}
public void setQueryService(BlockchainQueryService queryService) {
this.queryService = queryService;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy