概述
目录
- 概述
- 1. 项目结构
- 2. 数据库结构
- 3. 主要流程
- 3.1 服务启动
- 3.2 交易处理
- 3.3 加密交易
- 4. Restful API
- 4.1 Q2TRestApp
- 4.2 ThirdPartyRestApp
- 4.3 P2PRestApp
- 4.4 EnclaveApplication
- 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-config.json 示例
- tessera-dist/tessera-app/src/main/resources/tessera-spring.xml
- tessera-core/src/main/resources/tessera-core-spring.xml
- tessera-partyinfo/src/main/resources/tessera-partyinfo-spring.xml
概述
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>
最后
以上就是阳光秋天为你收集整理的【quorum源码】quorum tessera源码剖析的全部内容,希望文章能够帮你解决【quorum源码】quorum tessera源码剖析所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复