|
|
@@ -2,6 +2,8 @@ package com.jd.blockchain.mocker; |
|
|
|
|
|
|
|
import static java.lang.reflect.Proxy.newProxyInstance; |
|
|
|
|
|
|
|
import java.text.SimpleDateFormat; |
|
|
|
import java.util.Date; |
|
|
|
import java.util.HashMap; |
|
|
|
import java.util.Map; |
|
|
|
import java.util.Properties; |
|
|
@@ -46,424 +48,432 @@ import com.jd.blockchain.web.serializes.ByteArrayObjectUtil; |
|
|
|
|
|
|
|
public class MockerNodeContext implements BlockchainQueryService { |
|
|
|
|
|
|
|
private static final String[] SUPPORTED_PROVIDERS = { ClassicCryptoService.class.getName(), |
|
|
|
SMCryptoService.class.getName() }; |
|
|
|
private static final String[] SUPPORTED_PROVIDERS = { ClassicCryptoService.class.getName(), |
|
|
|
SMCryptoService.class.getName() }; |
|
|
|
|
|
|
|
private static final DBConnectionConfig dbConnectionConfig = new DBConnectionConfig("memory://local/0"); |
|
|
|
|
|
|
|
private static final DBConnectionConfig dbConnectionConfig = new DBConnectionConfig("memory://local/0"); |
|
|
|
private DbConnectionFactory dbConnFactory = new MemoryDBConnFactory(); |
|
|
|
|
|
|
|
private DbConnectionFactory dbConnFactory = new MemoryDBConnFactory(); |
|
|
|
private MockerOperationHandleRegister opHandler = new MockerOperationHandleRegister(); |
|
|
|
|
|
|
|
private MockerOperationHandleRegister opHandler = new MockerOperationHandleRegister(); |
|
|
|
private MockerContractExeHandle contractExeHandle = new MockerContractExeHandle(); |
|
|
|
|
|
|
|
private MockerContractExeHandle contractExeHandle = new MockerContractExeHandle(); |
|
|
|
private Map<String, BlockchainKeypair> participants = new HashMap<>(); |
|
|
|
|
|
|
|
private Map<String, BlockchainKeypair> participants = new HashMap<>(); |
|
|
|
private LedgerManager ledgerManager = new LedgerManager(); |
|
|
|
|
|
|
|
private LedgerManager ledgerManager = new LedgerManager(); |
|
|
|
private BlockchainKeypair defaultKeypair; |
|
|
|
|
|
|
|
private BlockchainKeypair defaultKeypair; |
|
|
|
private LedgerRepository ledgerRepository; |
|
|
|
|
|
|
|
private LedgerRepository ledgerRepository; |
|
|
|
private LedgerQueryService queryService; |
|
|
|
|
|
|
|
private LedgerQueryService queryService; |
|
|
|
private HashDigest ledgerHash; |
|
|
|
|
|
|
|
private HashDigest ledgerHash; |
|
|
|
private String ledgerSeed; |
|
|
|
|
|
|
|
private String ledgerSeed; |
|
|
|
static { |
|
|
|
DataContractRegistry.register(TransactionContent.class); |
|
|
|
DataContractRegistry.register(TransactionContentBody.class); |
|
|
|
DataContractRegistry.register(TransactionRequest.class); |
|
|
|
DataContractRegistry.register(NodeRequest.class); |
|
|
|
DataContractRegistry.register(EndpointRequest.class); |
|
|
|
DataContractRegistry.register(TransactionResponse.class); |
|
|
|
|
|
|
|
static { |
|
|
|
DataContractRegistry.register(TransactionContent.class); |
|
|
|
DataContractRegistry.register(TransactionContentBody.class); |
|
|
|
DataContractRegistry.register(TransactionRequest.class); |
|
|
|
DataContractRegistry.register(NodeRequest.class); |
|
|
|
DataContractRegistry.register(EndpointRequest.class); |
|
|
|
DataContractRegistry.register(TransactionResponse.class); |
|
|
|
|
|
|
|
DataContractRegistry.register(Operation.class); |
|
|
|
DataContractRegistry.register(ContractCodeDeployOperation.class); |
|
|
|
DataContractRegistry.register(ContractEventSendOperation.class); |
|
|
|
DataContractRegistry.register(DataAccountRegisterOperation.class); |
|
|
|
DataContractRegistry.register(UserRegisterOperation.class); |
|
|
|
DataContractRegistry.register(DataAccountKVSetOperation.class); |
|
|
|
DataContractRegistry.register(DataAccountKVSetOperation.KVWriteEntry.class); |
|
|
|
|
|
|
|
DataContractRegistry.register(ActionRequest.class); |
|
|
|
DataContractRegistry.register(ActionResponse.class); |
|
|
|
DataContractRegistry.register(ClientIdentifications.class); |
|
|
|
DataContractRegistry.register(ClientIdentification.class); |
|
|
|
|
|
|
|
ByteArrayObjectUtil.init(); |
|
|
|
} |
|
|
|
|
|
|
|
public MockerNodeContext() { |
|
|
|
} |
|
|
|
|
|
|
|
public MockerNodeContext(String ledgerSeed) { |
|
|
|
this.ledgerSeed = ledgerSeed; |
|
|
|
} |
|
|
|
|
|
|
|
public MockerNodeContext participants(String name, BlockchainKeypair partiKey) { |
|
|
|
participants.put(name, partiKey); |
|
|
|
return this; |
|
|
|
} |
|
|
|
|
|
|
|
public MockerNodeContext participants(BlockchainKeypair partiKey) { |
|
|
|
participants.put(partiKey.getPubKey().toBase58(), partiKey); |
|
|
|
return this; |
|
|
|
} |
|
|
|
|
|
|
|
public MockerNodeContext build() { |
|
|
|
if (ledgerSeed == null || ledgerSeed.length() == 0) { |
|
|
|
ledgerSeed = MockerConstant.DEFAULT_LEDGER_SEED; |
|
|
|
} |
|
|
|
if (participants.size() < 4) { |
|
|
|
// 缺少的需要补充,使用常量中的内容进行补充 |
|
|
|
for (int i = 0; i < MockerConstant.PUBLIC_KEYS.length; i++) { |
|
|
|
String pubKeyString = MockerConstant.PUBLIC_KEYS[i]; |
|
|
|
boolean isExist = false; |
|
|
|
// 通过公钥进行判断 |
|
|
|
for (Map.Entry<String, BlockchainKeypair> entry : participants.entrySet()) { |
|
|
|
String existPubKey = KeyGenCommand.encodePubKey(entry.getValue().getPubKey()); |
|
|
|
if (pubKeyString.equals(existPubKey)) { |
|
|
|
isExist = true; |
|
|
|
} |
|
|
|
} |
|
|
|
if (!isExist) { |
|
|
|
// 加入系统中 |
|
|
|
PrivKey privKey = KeyGenCommand.decodePrivKeyWithRawPassword(MockerConstant.PRIVATE_KEYS[i], MockerConstant.PASSWORD); |
|
|
|
PubKey pubKey = KeyGenCommand.decodePubKey(MockerConstant.PUBLIC_KEYS[i]); |
|
|
|
participants(new BlockchainKeypair(pubKey, privKey)); |
|
|
|
} |
|
|
|
if (participants.size() >= 4) { |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
LedgerInitProperties ledgerInitProperties = loadInitSetting(); |
|
|
|
|
|
|
|
MockerLedgerInitializer mockLedgerInitializer = new MockerLedgerInitializer(dbConnFactory, ledgerManager); |
|
|
|
|
|
|
|
ledgerHash = mockLedgerInitializer.initialize(0, defaultKeypair.getPrivKey(), |
|
|
|
ledgerInitProperties, dbConnectionConfig, new PresetAnswerPrompter("N"), cryptoConfig()); |
|
|
|
|
|
|
|
ledgerRepository = registerLedger(ledgerHash, dbConnectionConfig); |
|
|
|
|
|
|
|
queryService = new LedgerQueryService(ledgerManager); |
|
|
|
|
|
|
|
contractExeHandle.initLedger(ledgerManager, ledgerHash); |
|
|
|
|
|
|
|
opHandler.registerHandler(contractExeHandle); |
|
|
|
|
|
|
|
return this; |
|
|
|
} |
|
|
|
|
|
|
|
public String registerUser(BlockchainKeypair user) { |
|
|
|
TxBuilder txBuilder = txBuilder(); |
|
|
|
txBuilder.users().register(user.getIdentity()); |
|
|
|
txProcess(txRequest(txBuilder)); |
|
|
|
return user.getAddress().toBase58(); |
|
|
|
} |
|
|
|
|
|
|
|
public String registerDataAccount(BlockchainKeypair dataAccount) { |
|
|
|
TxBuilder txBuilder = txBuilder(); |
|
|
|
txBuilder.dataAccounts().register(dataAccount.getIdentity()); |
|
|
|
txProcess(txRequest(txBuilder)); |
|
|
|
return dataAccount.getAddress().toBase58(); |
|
|
|
} |
|
|
|
|
|
|
|
public String registerDataAccount() { |
|
|
|
return registerDataAccount(BlockchainKeyGenerator.getInstance().generate()); |
|
|
|
} |
|
|
|
|
|
|
|
public void writeKv(String address, String key, String value, long version) { |
|
|
|
TxBuilder txBuilder = txBuilder(); |
|
|
|
txBuilder.dataAccount(address).setText(key, value, version); |
|
|
|
txProcess(txRequest(txBuilder)); |
|
|
|
} |
|
|
|
|
|
|
|
public void writeKv(String address, String key, long value, long version) { |
|
|
|
TxBuilder txBuilder = txBuilder(); |
|
|
|
txBuilder.dataAccount(address).setInt64(key, value, version); |
|
|
|
txProcess(txRequest(txBuilder)); |
|
|
|
} |
|
|
|
|
|
|
|
public void writeKv(String address, String key, byte[] value, long version) { |
|
|
|
TxBuilder txBuilder = txBuilder(); |
|
|
|
txBuilder.dataAccount(address).setBytes(key, value, version); |
|
|
|
txProcess(txRequest(txBuilder)); |
|
|
|
} |
|
|
|
|
|
|
|
public void writeKv(String address, String key, Bytes value, long version) { |
|
|
|
TxBuilder txBuilder = txBuilder(); |
|
|
|
txBuilder.dataAccount(address).setBytes(key, value, version); |
|
|
|
txProcess(txRequest(txBuilder)); |
|
|
|
} |
|
|
|
|
|
|
|
public <T> T deployContract(T contract) { |
|
|
|
// 首先发布合约 |
|
|
|
BlockchainIdentity identity = deployContract2Ledger(contract); |
|
|
|
// 生成代理对象 |
|
|
|
ContractProxy<T> contractProxy = new ContractProxy<>(identity, this, |
|
|
|
contract, contractExeHandle); |
|
|
|
|
|
|
|
T proxy = (T) newProxyInstance(contract.getClass().getClassLoader(), |
|
|
|
contract.getClass().getInterfaces(), contractProxy); |
|
|
|
|
|
|
|
return proxy; |
|
|
|
} |
|
|
|
|
|
|
|
private BlockchainIdentity deployContract2Ledger(Object contract) { |
|
|
|
BlockchainIdentity contractIdentity = BlockchainKeyGenerator.getInstance().generate().getIdentity(); |
|
|
|
// 合约发布 |
|
|
|
// 注意此处只是将其放入内存中,而不需要真正编译为字节码 |
|
|
|
TxBuilder txBuilder = txBuilder(); |
|
|
|
txBuilder.contracts().deploy(contractIdentity, BytesUtils.toBytes(contract.getClass().getName())); |
|
|
|
// 执行 |
|
|
|
txProcess(txRequest(txBuilder)); |
|
|
|
return contractIdentity; |
|
|
|
} |
|
|
|
|
|
|
|
public String getLedgerSeed() { |
|
|
|
return ledgerSeed; |
|
|
|
} |
|
|
|
|
|
|
|
public HashDigest getLedgerHash() { |
|
|
|
return ledgerHash; |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public HashDigest[] getLedgerHashs() { |
|
|
|
return queryService.getLedgerHashs(); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public LedgerInfo getLedger(HashDigest ledgerHash) { |
|
|
|
return queryService.getLedger(ledgerHash); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public ParticipantNode[] getConsensusParticipants(HashDigest ledgerHash) { |
|
|
|
return queryService.getConsensusParticipants(ledgerHash); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public LedgerMetadata getLedgerMetadata(HashDigest ledgerHash) { |
|
|
|
return queryService.getLedgerMetadata(ledgerHash); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public LedgerBlock getBlock(HashDigest ledgerHash, long height) { |
|
|
|
return queryService.getBlock(ledgerHash, height); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public LedgerBlock getBlock(HashDigest ledgerHash, HashDigest blockHash) { |
|
|
|
return queryService.getBlock(ledgerHash, blockHash); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public long getTransactionCount(HashDigest ledgerHash, long height) { |
|
|
|
return queryService.getTransactionCount(ledgerHash, height); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public long getTransactionCount(HashDigest ledgerHash, HashDigest blockHash) { |
|
|
|
return queryService.getTransactionCount(ledgerHash, blockHash); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public long getTransactionTotalCount(HashDigest ledgerHash) { |
|
|
|
return queryService.getTransactionTotalCount(ledgerHash); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public long getDataAccountCount(HashDigest ledgerHash, long height) { |
|
|
|
return queryService.getDataAccountCount(ledgerHash, height); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public long getDataAccountCount(HashDigest ledgerHash, HashDigest blockHash) { |
|
|
|
return queryService.getDataAccountCount(ledgerHash, blockHash); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public long getDataAccountTotalCount(HashDigest ledgerHash) { |
|
|
|
return queryService.getDataAccountTotalCount(ledgerHash); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public long getUserCount(HashDigest ledgerHash, long height) { |
|
|
|
return queryService.getUserCount(ledgerHash, height); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public long getUserCount(HashDigest ledgerHash, HashDigest blockHash) { |
|
|
|
return queryService.getUserCount(ledgerHash, blockHash); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public long getUserTotalCount(HashDigest ledgerHash) { |
|
|
|
return queryService.getUserTotalCount(ledgerHash); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public long getContractCount(HashDigest ledgerHash, long height) { |
|
|
|
return queryService.getContractCount(ledgerHash, height); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public long getContractCount(HashDigest ledgerHash, HashDigest blockHash) { |
|
|
|
return queryService.getContractCount(ledgerHash, blockHash); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public long getContractTotalCount(HashDigest ledgerHash) { |
|
|
|
return queryService.getContractTotalCount(ledgerHash); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public LedgerTransaction[] getTransactions(HashDigest ledgerHash, long height, int fromIndex, int count) { |
|
|
|
return queryService.getTransactions(ledgerHash, height, fromIndex, count); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public LedgerTransaction[] getTransactions(HashDigest ledgerHash, HashDigest blockHash, int fromIndex, int count) { |
|
|
|
return queryService.getTransactions(ledgerHash, blockHash, fromIndex, count); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public LedgerTransaction getTransactionByContentHash(HashDigest ledgerHash, HashDigest contentHash) { |
|
|
|
return queryService.getTransactionByContentHash(ledgerHash, contentHash); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public TransactionState getTransactionStateByContentHash(HashDigest ledgerHash, HashDigest contentHash) { |
|
|
|
return queryService.getTransactionStateByContentHash(ledgerHash, contentHash); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public UserInfo getUser(HashDigest ledgerHash, String address) { |
|
|
|
return queryService.getUser(ledgerHash, address); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public AccountHeader getDataAccount(HashDigest ledgerHash, String address) { |
|
|
|
return queryService.getDataAccount(ledgerHash, address); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public KVDataEntry[] getDataEntries(HashDigest ledgerHash, String address, String... keys) { |
|
|
|
return queryService.getDataEntries(ledgerHash, address, keys); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public KVDataEntry[] getDataEntries(HashDigest ledgerHash, String address, KVInfoVO kvInfoVO) { |
|
|
|
return queryService.getDataEntries(ledgerHash, address, kvInfoVO); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public long getDataEntriesTotalCount(HashDigest ledgerHash, String address) { |
|
|
|
return queryService.getDataEntriesTotalCount(ledgerHash, address); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public KVDataEntry[] getDataEntries(HashDigest ledgerHash, String address, int fromIndex, int count) { |
|
|
|
return queryService.getDataEntries(ledgerHash, address, fromIndex, count); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public AccountHeader getContract(HashDigest ledgerHash, String address) { |
|
|
|
return queryService.getContract(ledgerHash, address); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public AccountHeader[] getUsers(HashDigest ledgerHash, int fromIndex, int count) { |
|
|
|
return queryService.getUsers(ledgerHash, fromIndex, count); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public AccountHeader[] getDataAccounts(HashDigest ledgerHash, int fromIndex, int count) { |
|
|
|
return queryService.getDataAccounts(ledgerHash, fromIndex, count); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public AccountHeader[] getContractAccounts(HashDigest ledgerHash, int fromIndex, int count) { |
|
|
|
return queryService.getContractAccounts(ledgerHash, fromIndex, count); |
|
|
|
} |
|
|
|
|
|
|
|
public TxBuilder txBuilder() { |
|
|
|
return new TxBuilder(ledgerHash); |
|
|
|
} |
|
|
|
|
|
|
|
public TransactionRequest txRequest(TxBuilder txBuilder) { |
|
|
|
TransactionRequestBuilder reqBuilder = txBuilder.prepareRequest(); |
|
|
|
reqBuilder.signAsEndpoint(defaultKeypair); |
|
|
|
return reqBuilder.buildRequest(); |
|
|
|
} |
|
|
|
|
|
|
|
public OperationResult[] txProcess(TransactionRequest txRequest) { |
|
|
|
LedgerEditor newEditor = ledgerRepository.createNextBlock(); |
|
|
|
LedgerBlock latestBlock = ledgerRepository.getLatestBlock(); |
|
|
|
LedgerDataSet previousDataSet = ledgerRepository.getDataSet(latestBlock); |
|
|
|
TransactionBatchProcessor txProc = new TransactionBatchProcessor(newEditor, previousDataSet, opHandler, |
|
|
|
ledgerManager); |
|
|
|
TransactionResponse txResp = txProc.schedule(txRequest); |
|
|
|
TransactionBatchResultHandle handle = txProc.prepare(); |
|
|
|
handle.commit(); |
|
|
|
return txResp.getOperationResults(); |
|
|
|
} |
|
|
|
|
|
|
|
private LedgerRepository registerLedger(HashDigest ledgerHash, DBConnectionConfig dbConnConf) { |
|
|
|
return ledgerManager.register(ledgerHash, dbConnFactory.connect(dbConnConf.getUri()).getStorageService()); |
|
|
|
} |
|
|
|
|
|
|
|
private CryptoConfig cryptoConfig() { |
|
|
|
CryptoProvider[] supportedProviders = new CryptoProvider[SUPPORTED_PROVIDERS.length]; |
|
|
|
for (int i = 0; i < SUPPORTED_PROVIDERS.length; i++) { |
|
|
|
supportedProviders[i] = Crypto.getProvider(SUPPORTED_PROVIDERS[i]); |
|
|
|
} |
|
|
|
CryptoConfig cryptoSetting = new CryptoConfig(); |
|
|
|
cryptoSetting.setSupportedProviders(supportedProviders); |
|
|
|
cryptoSetting.setAutoVerifyHash(false); |
|
|
|
cryptoSetting.setHashAlgorithm(ClassicAlgorithm.SHA256); |
|
|
|
return cryptoSetting; |
|
|
|
} |
|
|
|
|
|
|
|
private LedgerInitProperties loadInitSetting() { |
|
|
|
|
|
|
|
Properties ledgerProp = new Properties(); |
|
|
|
|
|
|
|
ledgerProp.put(LedgerInitProperties.LEDGER_SEED, ledgerSeed); |
|
|
|
|
|
|
|
ledgerProp.put("ledger.name", MockerConstant.LEDGER_NAME); |
|
|
|
|
|
|
|
ledgerProp.put(LedgerInitProperties.CONSENSUS_SERVICE_PROVIDER, "com.jd.blockchain.consensus.bftsmart.BftsmartConsensusProvider"); |
|
|
|
|
|
|
|
ledgerProp.put(LedgerInitProperties.CONSENSUS_CONFIG, "classpath:bftsmart.config"); |
|
|
|
|
|
|
|
ledgerProp.put(LedgerInitProperties.CRYPTO_SERVICE_PROVIDERS, "com.jd.blockchain.crypto.service.classic.ClassicCryptoService," + |
|
|
|
"com.jd.blockchain.crypto.service.sm.SMCryptoService"); |
|
|
|
|
|
|
|
ledgerProp.put(LedgerInitProperties.PART_COUNT, String.valueOf(participants.size())); |
|
|
|
|
|
|
|
int partiIndex = 0; |
|
|
|
for (Map.Entry<String, BlockchainKeypair> entry : participants.entrySet()) { |
|
|
|
String name = entry.getKey(); |
|
|
|
BlockchainKeypair keypair = entry.getValue(); |
|
|
|
if (partiIndex == 0) { |
|
|
|
defaultKeypair = keypair; |
|
|
|
} |
|
|
|
String partiPrefix = String.format(LedgerInitProperties.PART_ID_PATTERN, partiIndex) + "."; |
|
|
|
ledgerProp.put(partiPrefix + LedgerInitProperties.PART_NAME, name); |
|
|
|
ledgerProp.put(partiPrefix + LedgerInitProperties.PART_PUBKEY_PATH, ""); |
|
|
|
ledgerProp.put(partiPrefix + LedgerInitProperties.PART_PUBKEY, KeyGenCommand.encodePubKey(keypair.getPubKey())); |
|
|
|
ledgerProp.put(partiPrefix + LedgerInitProperties.PART_INITIALIZER_HOST, MockerConstant.LOCAL_ADDRESS); |
|
|
|
ledgerProp.put(partiPrefix + LedgerInitProperties.PART_INITIALIZER_PORT, String.valueOf(MockerConstant.LEDGER_INIT_PORT_START + partiIndex * 10)); |
|
|
|
ledgerProp.put(partiPrefix + LedgerInitProperties.PART_INITIALIZER_SECURE, String.valueOf(false)); |
|
|
|
partiIndex++; |
|
|
|
} |
|
|
|
|
|
|
|
return LedgerInitProperties.resolve(ledgerProp); |
|
|
|
} |
|
|
|
DataContractRegistry.register(Operation.class); |
|
|
|
DataContractRegistry.register(ContractCodeDeployOperation.class); |
|
|
|
DataContractRegistry.register(ContractEventSendOperation.class); |
|
|
|
DataContractRegistry.register(DataAccountRegisterOperation.class); |
|
|
|
DataContractRegistry.register(UserRegisterOperation.class); |
|
|
|
DataContractRegistry.register(DataAccountKVSetOperation.class); |
|
|
|
DataContractRegistry.register(DataAccountKVSetOperation.KVWriteEntry.class); |
|
|
|
|
|
|
|
DataContractRegistry.register(ActionRequest.class); |
|
|
|
DataContractRegistry.register(ActionResponse.class); |
|
|
|
DataContractRegistry.register(ClientIdentifications.class); |
|
|
|
DataContractRegistry.register(ClientIdentification.class); |
|
|
|
|
|
|
|
ByteArrayObjectUtil.init(); |
|
|
|
} |
|
|
|
|
|
|
|
public MockerNodeContext() { |
|
|
|
} |
|
|
|
|
|
|
|
public MockerNodeContext(String ledgerSeed) { |
|
|
|
this.ledgerSeed = ledgerSeed; |
|
|
|
} |
|
|
|
|
|
|
|
public MockerNodeContext participants(String name, BlockchainKeypair partiKey) { |
|
|
|
participants.put(name, partiKey); |
|
|
|
return this; |
|
|
|
} |
|
|
|
|
|
|
|
public MockerNodeContext participants(BlockchainKeypair partiKey) { |
|
|
|
participants.put(partiKey.getPubKey().toBase58(), partiKey); |
|
|
|
return this; |
|
|
|
} |
|
|
|
|
|
|
|
public MockerNodeContext build() { |
|
|
|
if (ledgerSeed == null || ledgerSeed.length() == 0) { |
|
|
|
ledgerSeed = MockerConstant.DEFAULT_LEDGER_SEED; |
|
|
|
} |
|
|
|
if (participants.size() < 4) { |
|
|
|
// 缺少的需要补充,使用常量中的内容进行补充 |
|
|
|
for (int i = 0; i < MockerConstant.PUBLIC_KEYS.length; i++) { |
|
|
|
String pubKeyString = MockerConstant.PUBLIC_KEYS[i]; |
|
|
|
boolean isExist = false; |
|
|
|
// 通过公钥进行判断 |
|
|
|
for (Map.Entry<String, BlockchainKeypair> entry : participants.entrySet()) { |
|
|
|
String existPubKey = KeyGenCommand.encodePubKey(entry.getValue().getPubKey()); |
|
|
|
if (pubKeyString.equals(existPubKey)) { |
|
|
|
isExist = true; |
|
|
|
} |
|
|
|
} |
|
|
|
if (!isExist) { |
|
|
|
// 加入系统中 |
|
|
|
PrivKey privKey = KeyGenCommand.decodePrivKeyWithRawPassword(MockerConstant.PRIVATE_KEYS[i], |
|
|
|
MockerConstant.PASSWORD); |
|
|
|
PubKey pubKey = KeyGenCommand.decodePubKey(MockerConstant.PUBLIC_KEYS[i]); |
|
|
|
participants(new BlockchainKeypair(pubKey, privKey)); |
|
|
|
} |
|
|
|
if (participants.size() >= 4) { |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
LedgerInitProperties ledgerInitProperties = loadInitSetting(); |
|
|
|
|
|
|
|
MockerLedgerInitializer mockLedgerInitializer = new MockerLedgerInitializer(dbConnFactory, ledgerManager); |
|
|
|
|
|
|
|
ledgerHash = mockLedgerInitializer.initialize(0, defaultKeypair.getPrivKey(), ledgerInitProperties, |
|
|
|
dbConnectionConfig, new PresetAnswerPrompter("N"), cryptoConfig()); |
|
|
|
|
|
|
|
ledgerRepository = registerLedger(ledgerHash, dbConnectionConfig); |
|
|
|
|
|
|
|
queryService = new LedgerQueryService(ledgerManager); |
|
|
|
|
|
|
|
contractExeHandle.initLedger(ledgerManager, ledgerHash); |
|
|
|
|
|
|
|
opHandler.registerHandler(contractExeHandle); |
|
|
|
|
|
|
|
return this; |
|
|
|
} |
|
|
|
|
|
|
|
public String registerUser(BlockchainKeypair user) { |
|
|
|
TxBuilder txBuilder = txBuilder(); |
|
|
|
txBuilder.users().register(user.getIdentity()); |
|
|
|
txProcess(txRequest(txBuilder)); |
|
|
|
return user.getAddress().toBase58(); |
|
|
|
} |
|
|
|
|
|
|
|
public String registerDataAccount(BlockchainKeypair dataAccount) { |
|
|
|
TxBuilder txBuilder = txBuilder(); |
|
|
|
txBuilder.dataAccounts().register(dataAccount.getIdentity()); |
|
|
|
txProcess(txRequest(txBuilder)); |
|
|
|
return dataAccount.getAddress().toBase58(); |
|
|
|
} |
|
|
|
|
|
|
|
public String registerDataAccount() { |
|
|
|
return registerDataAccount(BlockchainKeyGenerator.getInstance().generate()); |
|
|
|
} |
|
|
|
|
|
|
|
public void writeKv(String address, String key, String value, long version) { |
|
|
|
TxBuilder txBuilder = txBuilder(); |
|
|
|
txBuilder.dataAccount(address).setText(key, value, version); |
|
|
|
txProcess(txRequest(txBuilder)); |
|
|
|
} |
|
|
|
|
|
|
|
public void writeKv(String address, String key, long value, long version) { |
|
|
|
TxBuilder txBuilder = txBuilder(); |
|
|
|
txBuilder.dataAccount(address).setInt64(key, value, version); |
|
|
|
txProcess(txRequest(txBuilder)); |
|
|
|
} |
|
|
|
|
|
|
|
public void writeKv(String address, String key, byte[] value, long version) { |
|
|
|
TxBuilder txBuilder = txBuilder(); |
|
|
|
txBuilder.dataAccount(address).setBytes(key, value, version); |
|
|
|
txProcess(txRequest(txBuilder)); |
|
|
|
} |
|
|
|
|
|
|
|
public void writeKv(String address, String key, Bytes value, long version) { |
|
|
|
TxBuilder txBuilder = txBuilder(); |
|
|
|
txBuilder.dataAccount(address).setBytes(key, value, version); |
|
|
|
txProcess(txRequest(txBuilder)); |
|
|
|
} |
|
|
|
|
|
|
|
public <T> T deployContract(T contract) { |
|
|
|
// 首先发布合约 |
|
|
|
BlockchainIdentity identity = deployContract2Ledger(contract); |
|
|
|
// 生成代理对象 |
|
|
|
ContractProxy<T> contractProxy = new ContractProxy<>(identity, this, contract, contractExeHandle); |
|
|
|
|
|
|
|
T proxy = (T) newProxyInstance(contract.getClass().getClassLoader(), contract.getClass().getInterfaces(), |
|
|
|
contractProxy); |
|
|
|
|
|
|
|
return proxy; |
|
|
|
} |
|
|
|
|
|
|
|
private BlockchainIdentity deployContract2Ledger(Object contract) { |
|
|
|
BlockchainIdentity contractIdentity = BlockchainKeyGenerator.getInstance().generate().getIdentity(); |
|
|
|
// 合约发布 |
|
|
|
// 注意此处只是将其放入内存中,而不需要真正编译为字节码 |
|
|
|
TxBuilder txBuilder = txBuilder(); |
|
|
|
txBuilder.contracts().deploy(contractIdentity, BytesUtils.toBytes(contract.getClass().getName())); |
|
|
|
// 执行 |
|
|
|
txProcess(txRequest(txBuilder)); |
|
|
|
return contractIdentity; |
|
|
|
} |
|
|
|
|
|
|
|
public String getLedgerSeed() { |
|
|
|
return ledgerSeed; |
|
|
|
} |
|
|
|
|
|
|
|
public HashDigest getLedgerHash() { |
|
|
|
return ledgerHash; |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public HashDigest[] getLedgerHashs() { |
|
|
|
return queryService.getLedgerHashs(); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public LedgerInfo getLedger(HashDigest ledgerHash) { |
|
|
|
return queryService.getLedger(ledgerHash); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public ParticipantNode[] getConsensusParticipants(HashDigest ledgerHash) { |
|
|
|
return queryService.getConsensusParticipants(ledgerHash); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public LedgerMetadata getLedgerMetadata(HashDigest ledgerHash) { |
|
|
|
return queryService.getLedgerMetadata(ledgerHash); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public LedgerBlock getBlock(HashDigest ledgerHash, long height) { |
|
|
|
return queryService.getBlock(ledgerHash, height); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public LedgerBlock getBlock(HashDigest ledgerHash, HashDigest blockHash) { |
|
|
|
return queryService.getBlock(ledgerHash, blockHash); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public long getTransactionCount(HashDigest ledgerHash, long height) { |
|
|
|
return queryService.getTransactionCount(ledgerHash, height); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public long getTransactionCount(HashDigest ledgerHash, HashDigest blockHash) { |
|
|
|
return queryService.getTransactionCount(ledgerHash, blockHash); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public long getTransactionTotalCount(HashDigest ledgerHash) { |
|
|
|
return queryService.getTransactionTotalCount(ledgerHash); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public long getDataAccountCount(HashDigest ledgerHash, long height) { |
|
|
|
return queryService.getDataAccountCount(ledgerHash, height); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public long getDataAccountCount(HashDigest ledgerHash, HashDigest blockHash) { |
|
|
|
return queryService.getDataAccountCount(ledgerHash, blockHash); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public long getDataAccountTotalCount(HashDigest ledgerHash) { |
|
|
|
return queryService.getDataAccountTotalCount(ledgerHash); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public long getUserCount(HashDigest ledgerHash, long height) { |
|
|
|
return queryService.getUserCount(ledgerHash, height); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public long getUserCount(HashDigest ledgerHash, HashDigest blockHash) { |
|
|
|
return queryService.getUserCount(ledgerHash, blockHash); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public long getUserTotalCount(HashDigest ledgerHash) { |
|
|
|
return queryService.getUserTotalCount(ledgerHash); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public long getContractCount(HashDigest ledgerHash, long height) { |
|
|
|
return queryService.getContractCount(ledgerHash, height); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public long getContractCount(HashDigest ledgerHash, HashDigest blockHash) { |
|
|
|
return queryService.getContractCount(ledgerHash, blockHash); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public long getContractTotalCount(HashDigest ledgerHash) { |
|
|
|
return queryService.getContractTotalCount(ledgerHash); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public LedgerTransaction[] getTransactions(HashDigest ledgerHash, long height, int fromIndex, int count) { |
|
|
|
return queryService.getTransactions(ledgerHash, height, fromIndex, count); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public LedgerTransaction[] getTransactions(HashDigest ledgerHash, HashDigest blockHash, int fromIndex, int count) { |
|
|
|
return queryService.getTransactions(ledgerHash, blockHash, fromIndex, count); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public LedgerTransaction getTransactionByContentHash(HashDigest ledgerHash, HashDigest contentHash) { |
|
|
|
return queryService.getTransactionByContentHash(ledgerHash, contentHash); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public TransactionState getTransactionStateByContentHash(HashDigest ledgerHash, HashDigest contentHash) { |
|
|
|
return queryService.getTransactionStateByContentHash(ledgerHash, contentHash); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public UserInfo getUser(HashDigest ledgerHash, String address) { |
|
|
|
return queryService.getUser(ledgerHash, address); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public AccountHeader getDataAccount(HashDigest ledgerHash, String address) { |
|
|
|
return queryService.getDataAccount(ledgerHash, address); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public KVDataEntry[] getDataEntries(HashDigest ledgerHash, String address, String... keys) { |
|
|
|
return queryService.getDataEntries(ledgerHash, address, keys); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public KVDataEntry[] getDataEntries(HashDigest ledgerHash, String address, KVInfoVO kvInfoVO) { |
|
|
|
return queryService.getDataEntries(ledgerHash, address, kvInfoVO); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public long getDataEntriesTotalCount(HashDigest ledgerHash, String address) { |
|
|
|
return queryService.getDataEntriesTotalCount(ledgerHash, address); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public KVDataEntry[] getDataEntries(HashDigest ledgerHash, String address, int fromIndex, int count) { |
|
|
|
return queryService.getDataEntries(ledgerHash, address, fromIndex, count); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public AccountHeader getContract(HashDigest ledgerHash, String address) { |
|
|
|
return queryService.getContract(ledgerHash, address); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public AccountHeader[] getUsers(HashDigest ledgerHash, int fromIndex, int count) { |
|
|
|
return queryService.getUsers(ledgerHash, fromIndex, count); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public AccountHeader[] getDataAccounts(HashDigest ledgerHash, int fromIndex, int count) { |
|
|
|
return queryService.getDataAccounts(ledgerHash, fromIndex, count); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public AccountHeader[] getContractAccounts(HashDigest ledgerHash, int fromIndex, int count) { |
|
|
|
return queryService.getContractAccounts(ledgerHash, fromIndex, count); |
|
|
|
} |
|
|
|
|
|
|
|
public TxBuilder txBuilder() { |
|
|
|
return new TxBuilder(ledgerHash); |
|
|
|
} |
|
|
|
|
|
|
|
public TransactionRequest txRequest(TxBuilder txBuilder) { |
|
|
|
TransactionRequestBuilder reqBuilder = txBuilder.prepareRequest(); |
|
|
|
reqBuilder.signAsEndpoint(defaultKeypair); |
|
|
|
return reqBuilder.buildRequest(); |
|
|
|
} |
|
|
|
|
|
|
|
public OperationResult[] txProcess(TransactionRequest txRequest) { |
|
|
|
LedgerEditor newEditor = ledgerRepository.createNextBlock(); |
|
|
|
LedgerBlock latestBlock = ledgerRepository.getLatestBlock(); |
|
|
|
LedgerDataSet previousDataSet = ledgerRepository.getDataSet(latestBlock); |
|
|
|
TransactionBatchProcessor txProc = new TransactionBatchProcessor(newEditor, previousDataSet, opHandler, |
|
|
|
ledgerManager); |
|
|
|
TransactionResponse txResp = txProc.schedule(txRequest); |
|
|
|
TransactionBatchResultHandle handle = txProc.prepare(); |
|
|
|
handle.commit(); |
|
|
|
return txResp.getOperationResults(); |
|
|
|
} |
|
|
|
|
|
|
|
private LedgerRepository registerLedger(HashDigest ledgerHash, DBConnectionConfig dbConnConf) { |
|
|
|
return ledgerManager.register(ledgerHash, dbConnFactory.connect(dbConnConf.getUri()).getStorageService()); |
|
|
|
} |
|
|
|
|
|
|
|
private CryptoConfig cryptoConfig() { |
|
|
|
CryptoProvider[] supportedProviders = new CryptoProvider[SUPPORTED_PROVIDERS.length]; |
|
|
|
for (int i = 0; i < SUPPORTED_PROVIDERS.length; i++) { |
|
|
|
supportedProviders[i] = Crypto.getProvider(SUPPORTED_PROVIDERS[i]); |
|
|
|
} |
|
|
|
CryptoConfig cryptoSetting = new CryptoConfig(); |
|
|
|
cryptoSetting.setSupportedProviders(supportedProviders); |
|
|
|
cryptoSetting.setAutoVerifyHash(false); |
|
|
|
cryptoSetting.setHashAlgorithm(ClassicAlgorithm.SHA256); |
|
|
|
return cryptoSetting; |
|
|
|
} |
|
|
|
|
|
|
|
private LedgerInitProperties loadInitSetting() { |
|
|
|
|
|
|
|
Properties ledgerProp = new Properties(); |
|
|
|
|
|
|
|
ledgerProp.put(LedgerInitProperties.LEDGER_SEED, ledgerSeed); |
|
|
|
|
|
|
|
Date now = new Date(); |
|
|
|
SimpleDateFormat format = new SimpleDateFormat(LedgerInitProperties.CREATED_TIME_FORMAT); |
|
|
|
ledgerProp.put(LedgerInitProperties.CREATED_TIME, format.format(now)); |
|
|
|
|
|
|
|
ledgerProp.put("ledger.name", MockerConstant.LEDGER_NAME); |
|
|
|
|
|
|
|
ledgerProp.put(LedgerInitProperties.CONSENSUS_SERVICE_PROVIDER, |
|
|
|
"com.jd.blockchain.consensus.bftsmart.BftsmartConsensusProvider"); |
|
|
|
|
|
|
|
ledgerProp.put(LedgerInitProperties.CONSENSUS_CONFIG, "classpath:bftsmart.config"); |
|
|
|
|
|
|
|
ledgerProp.put(LedgerInitProperties.CRYPTO_SERVICE_PROVIDERS, |
|
|
|
"com.jd.blockchain.crypto.service.classic.ClassicCryptoService," |
|
|
|
+ "com.jd.blockchain.crypto.service.sm.SMCryptoService"); |
|
|
|
|
|
|
|
ledgerProp.put(LedgerInitProperties.PART_COUNT, String.valueOf(participants.size())); |
|
|
|
|
|
|
|
int partiIndex = 0; |
|
|
|
for (Map.Entry<String, BlockchainKeypair> entry : participants.entrySet()) { |
|
|
|
String name = entry.getKey(); |
|
|
|
BlockchainKeypair keypair = entry.getValue(); |
|
|
|
if (partiIndex == 0) { |
|
|
|
defaultKeypair = keypair; |
|
|
|
} |
|
|
|
String partiPrefix = String.format(LedgerInitProperties.PART_ID_PATTERN, partiIndex) + "."; |
|
|
|
ledgerProp.put(partiPrefix + LedgerInitProperties.PART_NAME, name); |
|
|
|
ledgerProp.put(partiPrefix + LedgerInitProperties.PART_PUBKEY_PATH, ""); |
|
|
|
ledgerProp.put(partiPrefix + LedgerInitProperties.PART_PUBKEY, |
|
|
|
KeyGenCommand.encodePubKey(keypair.getPubKey())); |
|
|
|
ledgerProp.put(partiPrefix + LedgerInitProperties.PART_INITIALIZER_HOST, MockerConstant.LOCAL_ADDRESS); |
|
|
|
ledgerProp.put(partiPrefix + LedgerInitProperties.PART_INITIALIZER_PORT, |
|
|
|
String.valueOf(MockerConstant.LEDGER_INIT_PORT_START + partiIndex * 10)); |
|
|
|
ledgerProp.put(partiPrefix + LedgerInitProperties.PART_INITIALIZER_SECURE, String.valueOf(false)); |
|
|
|
partiIndex++; |
|
|
|
} |
|
|
|
|
|
|
|
return LedgerInitProperties.resolve(ledgerProp); |
|
|
|
} |
|
|
|
} |