大家好,又见面了,我是你们的朋友全栈君。
目录
-
- 概述
- 1. 项目结构
- 2. 数据库结构
- 3. 主要流程
- 4. Restful API
- 5. 一些核心接口
-
-
- App、Enclave相关的类图:
- com.quorum.tessera.server.TesseraServer
- com.quorum.tessera.key.generation.KeyGenerator
- com.quorum.tessera.encryption.Encryptor
- com.quorum.tessera.enclave.Enclave
- com.quorum.tessera.context.RuntimeContext
- com.quorum.tessera.partyinfo.PartyInfoService
- com.quorum.tessera.transaction.TransactionManager
- com.quorum.tessera.config.AppType
-
- 6. 主要配置文件
概述
tessera是quorum的一种隐私管理器实现,使用Java语言编写,用于对quorum隐私交易的加密、解密和分发。
原理参考:Quorum工作原理
1. 项目结构
tessera
├── argon2
hash函数库,类似的函数还有pbkdf2、bcrypt、 scrypt
├── cli
使用picocli实现的命令行tessera(包含子命令keygen|keyupdate|admin)
├── config
配置数据模型,给各个模块使用的配置
├── config-migration
提供命令行可以将Constellation TOML转换成Tessera JSON
├── data-migration
创建表结构
├── ddls
ddl语句,包含两张表(支持mysq、oracle、postgresql、h2、hsql、sqllite)
├── enclave
提供加密、解密接口/Restful api(调用encryption模块)
├── encryption
生成主密钥、共享密钥、加密解密payload、生成随机数等.实现有ec、jnacl、kalium三种
├── key-generation
公钥私钥生成,包含aws、azure、hashcorp三种实现
├── key-vault
密钥保险箱 ,有aws、azure、hashcorp三种实现,可将密钥保存在这些在线服务上
├── security
ssl通信相关工具
├── server
包含两个TesseraServer的实现:1、使用Jersey和Jetty 实现的RestServer;2 WebSocketServer
├── service-locator
获取服务实例,默认使用spring 配置文件 tessera-spring.xml中的定义(不使用注解?)
├── shared
大杂烩,包含一些工具类:控制台密码读取、ReflectCallback、JaxbCallback等CallBack
├── tessera-context
上下文,见下面的RuntimeContext
├── tessera-core
主要包含TransactionManager
├── tessera-data
主要包含EncryptedTransactionDAO、EncryptedRawTransactionDAO的实现
├── tessera-dist
系统launcher入口,包含tessera-spring.xml配置文件
├── tessera-jaxrs
系统RESTful API(OpenAPI)定义
├── tessera-partyinfo
参与者之间的服务发现、p2p连接、推送EncodedPayload到其他节点
├── tessera-sync
peer节点之间Transaction的同步
├── test-utils
测试mock工具
└── tests
测试用例
参考下面的接口和类
2. 数据库结构
存储hash
和加密playload
对应关系
CREATE TABLE ENCRYPTED_TRANSACTION (
ENCODED_PAYLOAD BLOB NOT NULL,
HASH VARBINARY(100) NOT NULL,
TIMESTAMP BIGINT, PRIMARY KEY (HASH)
);
CREATE TABLE ENCRYPTED_RAW_TRANSACTION (
ENCRYPTED_KEY BLOB NOT NULL,
ENCRYPTED_PAYLOAD BLOB NOT NULL,
NONCE BLOB NOT NULL,
SENDER BLOB NOT NULL,
TIMESTAMP BIGINT,
HASH VARBINARY(100) NOT NULL, PRIMARY KEY (HASH)
);
3. 主要流程
3.1 服务启动
a. 首先通过cli从配置文件tessera-config.json读取配置,根据配置创建运行时上下文(上下文持有当前节点公私钥对,peers列表等引用)
b. 再将当前partyInfo保存到集合中(内存)
c. 根据的serverConfigs循环创建ThirdPartyRestApp、P2PRestApp、Q2TRestApp(未包含EnclaveApplication)Restful服务
d 启动服务监听
顺序图:
主要代码:
main方法
PicoCliDelegate picoCliDelegate = new PicoCliDelegate();
LOGGER.debug("Execute PicoCliDelegate with args [{}]",String.join(",",args));
final CliResult cliResult = picoCliDelegate.execute(args);
LOGGER.debug("Executed PicoCliDelegate with args [{}].",String.join(",",args));
CliDelegate.instance().setConfig(cliResult.getConfig().orElse(null));
if (cliResult.isSuppressStartup()) {
System.exit(0);
}
if (cliResult.getStatus() != 0) {
System.exit(cliResult.getStatus());
}
final Config config =
cliResult
.getConfig()
.orElseThrow(() -> new NoSuchElementException("No config found. Tessera will not run."));
RuntimeContext runtimeContext = RuntimeContextFactory.newFactory().create(config);
LOGGER.debug("Creating service locator");
ServiceLocator serviceLocator = ServiceLocator.create();
LOGGER.debug("Created service locator {}",serviceLocator);
Set<Object> services = serviceLocator.getServices();
LOGGER.debug("Created {} services",services.size());
services.forEach(o -> LOGGER.debug("Service : {}",o));
services.stream()
.filter(PartyInfoService.class::isInstance)
.map(PartyInfoService.class::cast)
.findAny()
.ifPresent(p -> p.populateStore());
runWebServer(config);
runWebServer
final List<TesseraServer> servers =
config.getServerConfigs().stream()
.filter(server -> !AppType.ENCLAVE.equals(server.getApp()))
.map(
conf -> {
Object app =
TesseraAppFactory.create(conf.getCommunicationType(), conf.getApp())
.orElseThrow(
() ->
new IllegalStateException(
"Cant create app for " + conf.getApp()));
return TesseraServerFactory.create(conf.getCommunicationType())
.createServer(conf, Collections.singleton(app));
})
.filter(Objects::nonNull)
.collect(Collectors.toList());
for (TesseraServer ts : servers) {
ts.start();
}
3.2 交易处理
a.收到交易请求后,将请求交给TransactionManager处理,TransactionManager调用Enclave加密tx(详见下一个流程【加密交易】),根据加密的payload,调用MessageHashFactory生成tx Hash,
b. 调用DAO将数据保存到数据库
c. 循环接收者列表,将加密了的playload推送给其他Tessera节点处理
d.将tx hash使用base64编码后返回给quorum几点
主要代码:
public SendResponse send(SendRequest sendRequest) {
final String sender = sendRequest.getFrom();
final PublicKey senderPublicKey =
Optional.ofNullable(sender)
.map(base64Decoder::decode)
.map(PublicKey::from)
.orElseGet(enclave::defaultPublicKey);
final byte[][] recipients =
Stream.of(sendRequest)
.filter(sr -> Objects.nonNull(sr.getTo()))
.flatMap(s -> Stream.of(s.getTo()))
.map(base64Decoder::decode)
.toArray(byte[][]::new);
final List<PublicKey> recipientList = Stream.of(recipients).map(PublicKey::from).collect(Collectors.toList());
recipientList.add(senderPublicKey);
recipientList.addAll(enclave.getForwardingKeys());
final List<PublicKey> recipientListNoDuplicate =
recipientList.stream().distinct().collect(Collectors.toList());
final byte[] raw = sendRequest.getPayload();
final EncodedPayload payload = enclave.encryptPayload(raw, senderPublicKey, recipientListNoDuplicate);
final MessageHash transactionHash =
Optional.of(payload)
.map(EncodedPayload::getCipherText)
.map(messageHashFactory::createFromCipherText)
.get();
final EncryptedTransaction newTransaction =
new EncryptedTransaction(transactionHash, this.payloadEncoder.encode(payload));
this.encryptedTransactionDAO.save(newTransaction);
recipientListNoDuplicate.forEach(
recipient -> {
final EncodedPayload outgoing = payloadEncoder.forRecipient(payload, recipient);
partyInfoService.publishPayload(outgoing, recipient);
});
final byte[] key = transactionHash.getHashBytes();
final String encodedKey = base64Decoder.encodeToString(key);
return new SendResponse(encodedKey);
}
3.3 加密交易
a. 生成随机主密钥(RMK:NonceMasterKey)和随机数Nonce、接收者随机数Nonce
b.使用步骤a的随机数Nonce和RMK加密message(Transaction Payload)。
c. 根据发送者的公钥从keymanager中获取发送者私钥
d.遍历接收者列表:根据发送者的私钥和接收者的公钥生成共享秘钥,根据共享密钥和接收者随机数加密RMK,最后返回RMK列表
e.返回加密的playload、随机数、RMKs给Transaction Manager
注:图中使用的Encryptor实现是EllipticalCurveEncryptor
主要代码:
public EncodedPayload encryptPayload(
final RawTransaction rawTransaction, final List<PublicKey> recipientPublicKeys) {
final MasterKey masterKey =
this.getMasterKey(
rawTransaction.getFrom(), rawTransaction.getFrom(),
rawTransaction.getNonce(), rawTransaction.getEncryptedKey());
final Nonce recipientNonce = encryptor.randomNonce();
final List<byte[]> encryptedMasterKeys =
buildRecipientMasterKeys(rawTransaction.getFrom(), recipientPublicKeys, recipientNonce, masterKey);
return EncodedPayload.Builder.create()
.withSenderKey(rawTransaction.getFrom())
.withCipherText(rawTransaction.getEncryptedPayload())
.withCipherTextNonce(rawTransaction.getNonce())
.withRecipientBoxes(encryptedMasterKeys)
.withRecipientNonce(recipientNonce)
.withRecipientKeys(recipientPublicKeys)
.build();
}
private List<byte[]> buildRecipientMasterKeys(
final PublicKey senderPublicKey,
final List<PublicKey> recipientPublicKeys,
final Nonce recipientNonce,
final MasterKey masterKey) {
final PrivateKey privateKey = keyManager.getPrivateKeyForPublicKey(senderPublicKey);
return recipientPublicKeys.stream()
.map(publicKey -> encryptor.computeSharedKey(publicKey, privateKey))
.map(sharedKey -> encryptor.sealAfterPrecomputation(masterKey.getKeyBytes(), recipientNonce, sharedKey))
.collect(Collectors.toList());
}
4. Restful API
4.1 Q2TRestApp
quorum节点和tessera之间的数据交换
api | method | 功能 |
---|---|---|
send | post | Send private transaction payload |
sendRaw | post | Send private transaction payload |
sendsignedtx | post | Send private raw transaction payload |
receive | get | Submit keys to retrieve payload and decrypt it |
receiveRaw | get | Submit keys to retrieve payload and decrypt it |
transaction/{hash} | get | Returns decrypted payload back to Quorum |
transaction/{key} | delete | Delete single transaction from P2PRestApp node |
upcheck | get | Node is up? |
version | get | Node’s version |
storeraw | post | Store raw private transaction payload |
4.2 ThirdPartyRestApp
api | method | 功能 |
---|---|---|
key | get | Fetch local public keys managed by the enclave |
partyinfo/key | get | Fetch network/peer public keys |
storeraw | post | Store raw private transaction payload |
4.3 P2PRestApp
tessera节点之间的数据交换
api | method | 功能 |
---|---|---|
resend | post | Resend transactions for given key or message hash/recipient |
push | post | Transmit encrypted payload between P2PRestApp Nodes |
partyinfo | post | Request public key/url of other nodes |
partyinfo | get | Fetch network/peer information |
partyinfo/validate | post | validate network/peer |
4.4 EnclaveApplication
提供main方法,可以独立启动成web服务提供Restful API,也可以走内部调用(默认)
api | method | 功能 |
---|---|---|
ping | get | 获取Encalve服务状态 |
default | get | 获取默认的公钥(第一个) |
forwarding | get | 获取要转发的公钥列表 |
public | get | 获取公钥 |
encrypt | post | 加密playload |
encrypt/raw | post | 加密rawplayload |
encrypt/toraw | post | playload转换成rawplayload |
unencrypt | post | 解密Payload |
addRecipient | post | 添加收件人 |
5. 一些核心接口
App、Enclave相关的类图:
某些接口手工加了成员变量
com.quorum.tessera.server.TesseraServer
public interface TesseraServer {
void start() throws Exception;
void stop() throws Exception;
}
com.quorum.tessera.key.generation.KeyGenerator
public interface KeyGenerator {
ConfigKeyPair generate(String filename, ArgonOptions encryptionOptions, KeyVaultOptions keyVaultOptions);
}
com.quorum.tessera.encryption.Encryptor
/** * The API provided to the application that all implementation of this API * module should extend * <p> * Provides all function relating to encrypting and decrypting messages * using public/private and symmetric keys. */
public interface Encryptor {
/** * Compute the shared key from a public/private key combination * The keys must be from different keysets. * Providing the public key for the corresponding private key (and vice versa) results in an error * <p> * The shared key for a public/private key combo is the same as if the private/public corresponding keys * were provided. * i.e. public1/private2 == private1/public2 * * @param publicKey A public key from the first keyset * @param privateKey A private key from the second keyset * @return The shared key for this key pair. */
SharedKey computeSharedKey(PublicKey publicKey, PrivateKey privateKey);
/** * Encrypt a payload directly using the given public/private key pair for the sender/recipient * * @param message The payload to be encrypted * @param nonce A unique nonce for this public/private pair * @param publicKey The key from either sender or recipient * @param privateKey The other key from either sender or recipient * @return The encrypted payload */
byte[] seal(byte[] message, Nonce nonce, PublicKey publicKey, PrivateKey privateKey);
/** * Decrypt a payload directly using the given public/private key pair for the sender/recipient * * @param cipherText The payload to be encrypted * @param nonce A unique nonce for this public/private pair * @param publicKey The key from either sender or recipient * @param privateKey The other key from either sender or recipient * @return The encrypted payload */
byte[] open(byte[] cipherText, Nonce nonce, PublicKey publicKey, PrivateKey privateKey);
/** * Encrypt a payload using the given public/private key pair for the sender/recipient * * @param message The payload to be encrypted * @param nonce A unique nonce for this public/private pair * @param sharedKey The shared key between the sender and recipient of the payload * @return The encrypted payload */
byte[] sealAfterPrecomputation(byte[] message, Nonce nonce, SharedKey sharedKey);
default byte[] sealAfterPrecomputation(byte[] message, Nonce nonce, MasterKey masterKey) {
SharedKey sharedKey = SharedKey.from(masterKey.getKeyBytes());
return sealAfterPrecomputation(message, nonce, sharedKey);
}
/** * Decrypts a payload using the shared key between the sender and recipient * * @param cipherText The encrypted payload * @param nonce The nonce that was used to encrypt this payload * @param sharedKey The shared key for the sender and recipient * @return The decrypted payload */
byte[] openAfterPrecomputation(byte[] cipherText, Nonce nonce, SharedKey sharedKey);
/** * Generates a new random nonce of the correct size * * @return a {@link Nonce} containing random data to be used as a nonce */
Nonce randomNonce();
/** * Generates a new public and private keypair * * @return A pair of public and private keys */
KeyPair generateNewKeys();
/** * Creates a single standalone key * * @return The randomly generated key */
SharedKey createSingleKey();
/** * Create a randomly generated {@link MasterKey} * * @return a random {@link MasterKey} */
default MasterKey createMasterKey() {
SharedKey sharedKey = createSingleKey();
return MasterKey.from(sharedKey.getKeyBytes());
}
/** * Decrypts a payload using the given {@link MasterKey} * * @param cipherText the ciphertext to decrypt * @param cipherTextNonce the nonce that was used to encrypt the payload * @param masterKey the key used to encrypt the payload * @return the decrypted payload * @see Encryptor#openAfterPrecomputation(byte[], Nonce, SharedKey) */
default byte[] openAfterPrecomputation(byte[] cipherText, Nonce cipherTextNonce, MasterKey masterKey) {
SharedKey sharedKey = SharedKey.from(masterKey.getKeyBytes());
return openAfterPrecomputation(cipherText, cipherTextNonce, sharedKey);
}
}
com.quorum.tessera.enclave.Enclave
/** * An {@link Enclave} provides encryption/decryption functions and keeps hold * of all the nodes private keys so the do not leak into other services. */
public interface Enclave extends Service {
private final Encryptor encryptor;
private final KeyManager keyManager;
/** * Retrieves the public key to use if no key is specified for an operation * There is no guarantee this key remains the same between runs of the Enclave. * * @return the public key that has been assigned as the default */
PublicKey defaultPublicKey();
/** * Returns a set of public keys that should be included as recipients to * all transactions produced by this node. The keys are not be managed by * this node. * * @return the set of public keys to be added to transactions */
Set<PublicKey> getForwardingKeys();
/** * Returns all the public keys that are managed by this Enclave. * * @return all public keys managed by this Enclave */
Set<PublicKey> getPublicKeys();
/** * Encrypts a message using the specified sender and a list of recipients. * Returns a {@link EncodedPayload} which contains all the encrypted * information, including the recipients and their encrypted master keys. * * @param message the message to be encrypted * @param senderPublicKey the public key which this enclave manages * @param recipientPublicKeys the recipients to encrypt this message for * @return the encrypted information, represented by an {@link EncodedPayload} */
EncodedPayload encryptPayload(byte[] message, PublicKey senderPublicKey, List<PublicKey> recipientPublicKeys);
/** * Decrypts a {@link RawTransaction} so that it can be re-encrypted into a * {@link EncodedPayload} with the given recipient list * * @param rawTransaction the transactiopn to decrypt and re-encrypt with recipients * @param recipientPublicKeys the recipients to encrypt the transaction for * @return the encrypted information, represented by an {@link EncodedPayload} */
EncodedPayload encryptPayload(RawTransaction rawTransaction, List<PublicKey> recipientPublicKeys);
/** * Encrypt a payload without any recipients that can be retrieved later. * The payload is encrypted using the private key that is related to the * given public key. * * @param message the message to be encrypted * @param sender the sender's public key to encrypt the transaction with * @return the encrypted transaction */
RawTransaction encryptRawPayload(byte[] message, PublicKey sender);
/** * Decrypt a transaction and fetch the original message using the given * public key. Throws an {@link com.quorum.tessera.nacl.NaclException} if * the provided public key OR one of the Enclave's managed keys cannot be * used to decrypt the payload * * @param payload the encrypted payload * @param providedKey the key to use for decryption, if the payload wasn't sent by this Enclave * @return the original, decrypted message */
byte[] unencryptTransaction(EncodedPayload payload, PublicKey providedKey);
/** * Creates a new recipient box for the payload, for which we must be the originator. * At least one recipient must already be available to be able to decrypt the master key. * * @param payload the payload to add a recipient to * @param recipientKey the new recipient key to add */
byte[] createNewRecipientBox(EncodedPayload payload, PublicKey recipientKey);
@Override
default void start() {
}
@Override
default void stop() {
}
}
com.quorum.tessera.context.RuntimeContext
public interface RuntimeContext {
List<KeyPair> getKeys();
KeyEncryptor getKeyEncryptor();
List<PublicKey> getAlwaysSendTo();
List<URI> getPeers();
Client getP2pClient();
boolean isRemoteKeyValidation();
URI getP2pServerUri();
static RuntimeContext getInstance() {
return ContextHolder.INSTANCE.getContext().get();
}
boolean isDisablePeerDiscovery();
default Set<PublicKey> getPublicKeys() {
return getKeys().stream().map(KeyPair::getPublicKey).collect(Collectors.toSet());
}
boolean isUseWhiteList();
}
com.quorum.tessera.partyinfo.PartyInfoService
public interface PartyInfoService {
/** * Request PartyInfo data from all remote nodes that this node is aware of * * @return PartyInfo object */
PartyInfo getPartyInfo();
/** * Update the PartyInfo data store with the provided encoded data.This can happen when endpoint /partyinfo is * triggered, or by a response from this node hitting another node /partyinfo endpoint * * @param partyInfo * @return updated PartyInfo object */
PartyInfo updatePartyInfo(PartyInfo partyInfo);
// Set<String> getUrlsForKey(PublicKey key);
PartyInfo removeRecipient(String uri);
/** * Formats, encodes and publishes encrypted messages using the target public key as the identifier, instead of the * URL * * @param payload the pre-formatted payload object (i.e. with all recipients still present) * @param recipientKey the target public key to publish the payload to * @throws com.quorum.tessera.encryption.KeyNotFoundException if the target public key is not known */
void publishPayload(EncodedPayload payload, PublicKey recipientKey);
// TODO: Added as lifecycle call once RuntimeContext has been created.
void populateStore();
}
com.quorum.tessera.transaction.TransactionManager
public interface TransactionManager {
private final PayloadEncoder payloadEncoder;
private final Base64Decoder base64Decoder;
private final EncryptedTransactionDAO encryptedTransactionDAO;
private final EncryptedRawTransactionDAO encryptedRawTransactionDAO;
private final PartyInfoService partyInfoService;
private final Enclave enclave;
private final ResendManager resendManager;
private final MessageHashFactory messageHashFactory = MessageHashFactory.create();
private int resendFetchSize;
SendResponse send(SendRequest sendRequest);
SendResponse sendSignedTransaction(SendSignedRequest sendRequest);
void delete(DeleteRequest request);
ResendResponse resend(ResendRequest request);
MessageHash storePayload(byte[] toByteArray);
ReceiveResponse receive(ReceiveRequest request);
StoreRawResponse store(StoreRawRequest storeRequest);
}
com.quorum.tessera.config.AppType
public enum AppType {
P2P(CommunicationType.REST),
Q2T(CommunicationType.REST),
THIRD_PARTY(CommunicationType.REST),
ENCLAVE(CommunicationType.REST),
ADMIN(CommunicationType.REST);
}
6. 主要配置文件
tessera-config.json 示例
{
"useWhiteList": false,
"jdbc": {
"username": "sa",
"password": "",
"url": "jdbc:h2:test/db;MODE=Oracle;TRACE_LEVEL_SYSTEM_OUT=0",
"autoCreateTables": true
},
"serverConfigs":[
{
"app":"ThirdParty",
"enabled": true,
"serverAddress": "http://$$(hostname -i):9080",
"communicationType" : "REST"
},
{
"app":"Q2T",
"enabled": true,
"serverAddress": "unix:$${DDIR}/tm.ipc",
"communicationType" : "REST"
},
{
"app":"P2P",
"enabled": true,
"serverAddress": "http://$$(hostname -i):9000",
"sslConfig": {
"tls": "OFF"
},
"communicationType" : "REST"
}
],
"peer": [
{
"url": "http://txmanager1:9000"
},
{
"url": "http://txmanager2:9000"
},
{
"url": "http://txmanager3:9000"
},
{
"url": "http://txmanager4:9000"
},
{
"url": "http://txmanager5:9000"
},
{
"url": "http://txmanager6:9000"
},
{
"url": "http://txmanager7:9000"
}
],
"keys": {
"passwords": [],
"keyData": [
{
"config": "tm.key",
"publicKey": "tm.pub"
}
]
},
"alwaysSendTo": []
}
tessera-dist/tessera-app/src/main/resources/tessera-spring.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<import resource="classpath:/tessera-core-spring.xml" />
<import resource="classpath:/tessera-partyinfo-spring.xml" />
</beans>
tessera-core/src/main/resources/tessera-core-spring.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<tx:annotation-driven transaction-manager="jpaTransactionManager"/>
<context:component-scan base-package="com.quorum.tessera"/>
<bean id="enclaveFactory" class="com.quorum.tessera.enclave.EnclaveFactory" factory-method="create" />
<bean id="enclave" factory-bean="enclaveFactory" factory-method="create">
<constructor-arg ref="config" />
</bean>
<bean class="com.quorum.tessera.service.ServiceContainer">
<constructor-arg ref="enclave" />
</bean>
<bean id="transactionManager" class="com.quorum.tessera.transaction.TransactionManagerImpl">
<constructor-arg ref="encryptedTransactionDAO" />
<constructor-arg ref="enclave" />
<constructor-arg ref="encryptedRawTransactionDAO" />
<constructor-arg ref="resendManager" />
<constructor-arg ref="partyInfoService" />
<constructor-arg value="#{config.getJdbcConfig().getFetchSize() > 0 ? config.getJdbcConfig().getFetchSize() : 1000}"/>
</bean>
<bean id="cliDelegate" class="com.quorum.tessera.cli.CliDelegate" factory-method="instance"/>
<bean id="config" factory-bean="cliDelegate" factory-method="getConfig"/>
<bean name="encryptedTransactionDAO" class="com.quorum.tessera.data.EncryptedTransactionDAOImpl"/>
<bean name="encryptedRawTransactionDAO" class="com.quorum.tessera.data.EncryptedRawTransactionDAOImpl"/>
<bean id="dataSource" class="com.zaxxer.hikari.HikariDataSource">
<property name="jdbcUrl" value="#{ config.getJdbcConfig().getUrl() }" />
<property name="username" value="#{ config.getJdbcConfig().getUsername() }" />
<property name="password" value="#{ resolver.resolve(config.getJdbcConfig().getPassword()) }" />
</bean>
<bean id="jpaTransactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="persistenceUnitName" value="tessera"/>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.EclipseLinkJpaVendorAdapter" />
</property>
<property name="jpaDialect">
<bean class="org.springframework.orm.jpa.vendor.EclipseLinkJpaDialect"/>
</property>
<property name="jpaPropertyMap">
<props>
<prop key="eclipselink.weaving">false</prop>
<prop key="eclipselink.session-name">tessera</prop>
<prop key="eclipselink.logging.logger">org.eclipse.persistence.logging.slf4j.SLF4JLogger</prop>
<prop key="eclipselink.logging.session">false</prop>
<prop key="javax.persistence.schema-generation.database.action">#{config.getJdbcConfig().isAutoCreateTables() ? 'create' : 'none'}</prop>
</props>
</property>
</bean>
<bean id="resolver" class="com.quorum.tessera.config.util.EncryptedStringResolver"/>
</beans>
tessera-partyinfo/src/main/resources/tessera-partyinfo-spring.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="p2pClientFactory" class="com.quorum.tessera.partyinfo.P2pClientFactory" factory-method="newFactory">
<constructor-arg ref="config" />
</bean>
<bean id="p2pClient" factory-bean="p2pClientFactory" factory-method="create">
<constructor-arg ref="config"/>
</bean>
<bean id="resendClientFactory" class="com.quorum.tessera.sync.ResendClientFactory" factory-method="newFactory">
<constructor-arg ref="config"/>
</bean>
<bean id="resendClient" factory-bean="resendClientFactory" factory-method="create">
<constructor-arg ref="config"/>
</bean>
<bean id="payloadPublisherFactory" class="com.quorum.tessera.partyinfo.PayloadPublisherFactory" factory-method="newFactory">
<constructor-arg ref="config" />
</bean>
<bean id="payloadPublisher" class="com.quorum.tessera.partyinfo.PayloadPublisher" factory-bean="payloadPublisherFactory" factory-method="create">
<constructor-arg ref="config" />
</bean>
<!-- Party Info management -->
<bean name="partyInfoStore" class="com.quorum.tessera.partyinfo.PartyInfoStore">
<constructor-arg value="#{config.getP2PServerConfig().getServerUri()}"/>
</bean>
<bean name="partyInfoService" class="com.quorum.tessera.partyinfo.PartyInfoServiceImpl">
<constructor-arg ref="partyInfoStore"/>
<constructor-arg ref="enclave"/>
<constructor-arg ref="payloadPublisher"/>
</bean>
<bean name="partyInfoPoller" class="com.quorum.tessera.partyinfo.PartyInfoPoller">
<constructor-arg ref="partyInfoService"/>
<constructor-arg ref="p2pClient"/>
</bean>
<bean name="propertyHelper" class="com.quorum.tessera.config.util.IntervalPropertyHelper">
<constructor-arg value="#{config.getP2PServerConfig().getProperties()}"/>
</bean>
<bean name="partyInfoPollExecutor" class="com.quorum.tessera.threading.TesseraScheduledExecutor">
<constructor-arg>
<bean class="java.util.concurrent.Executors" factory-method="newSingleThreadScheduledExecutor"/>
</constructor-arg>
<constructor-arg ref="partyInfoPoller"/>
<constructor-arg value="#{propertyHelper.partyInfoInterval()}"/>
<constructor-arg value="5000"/>
</bean>
<bean id="resendManager" class="com.quorum.tessera.partyinfo.ResendManagerImpl">
<constructor-arg ref="encryptedTransactionDAO" />
<constructor-arg ref="enclave" />
</bean>
<!-- Local key sync -->
<bean name="enclaveKeySynchroniser" class="com.quorum.tessera.partyinfo.EnclaveKeySynchroniser">
<constructor-arg ref="enclave" />
<constructor-arg ref="partyInfoStore" />
<constructor-arg value="#{config.getP2PServerConfig().getServerUri()}" />
</bean>
<bean name="enclaveKeySynchroniserExecutor" class="com.quorum.tessera.threading.TesseraScheduledExecutor">
<constructor-arg>
<bean class="java.util.concurrent.Executors" factory-method="newSingleThreadScheduledExecutor"/>
</constructor-arg>
<constructor-arg ref="enclaveKeySynchroniser"/>
<constructor-arg value="#{propertyHelper.enclaveKeySyncInterval()}"/>
<constructor-arg value="5000"/>
</bean>
<!-- Node synchronization management-->
<beans profile="enable-sync-poller">
<bean name="resendPartyStore" class="com.quorum.tessera.sync.ResendPartyStoreImpl"/>
<bean name="transactionRequester" class="com.quorum.tessera.sync.TransactionRequesterImpl">
<constructor-arg ref="enclave" />
<constructor-arg ref="resendClient" />
</bean>
<bean name="syncPoller" class="com.quorum.tessera.sync.SyncPoller">
<constructor-arg ref="resendPartyStore" />
<constructor-arg ref="transactionRequester" />
<constructor-arg ref="partyInfoService"/>
<constructor-arg ref="p2pClient"/>
</bean>
<bean class="com.quorum.tessera.threading.TesseraScheduledExecutor">
<constructor-arg>
<bean class="java.util.concurrent.Executors" factory-method="newSingleThreadScheduledExecutor"/>
</constructor-arg>
<constructor-arg ref="syncPoller"/>
<constructor-arg value="#{propertyHelper.syncInterval()}"/>
<constructor-arg value="5000"/>
</bean>
</beans>
</beans>
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/138934.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...