+ * If updating is performed, the version of the key increase by 1.
+ * If creating is performed, the version of the key initialize by 0.
+ *
+ * @param key The key of data;
+ * @param value The value of data;
+ * @param version The expected version of the key.
+ * @return The new version of the key.
+ * If the key is new created success, then return 0;
+ * If the key is updated success, then return the new version;
+ * If this operation fail by version checking or other reason, then
+ * return -1;
+ */
public long setBytes(Bytes key, BytesValue value, long version) {
return baseAccount.setBytes(key, value, version);
}
+ /**
+ * Create or update the value associated the specified key if the version
+ * checking is passed.
+ *
+ * The value of the key will be updated only if it's latest version equals the
+ * specified version argument.
+ * If the key doesn't exist, the version checking will be ignored, and key will
+ * be created with a new sequence number as id.
+ * It also could specify the version argument to -1 to ignore the version
+ * checking.
+ *
+ * If updating is performed, the version of the key increase by 1.
+ * If creating is performed, the version of the key initialize by 0.
+ *
+ * @param key The key of data;
+ * @param value The value of data;
+ * @param version The expected version of the key.
+ * @return The new version of the key.
+ * If the key is new created success, then return 0;
+ * If the key is updated success, then return the new version;
+ * If this operation fail by version checking or other reason, then
+ * return -1;
+ */
public long setBytes(Bytes key, String value, long version) {
BytesValue bytesValue = BytesData.fromText(value);
return baseAccount.setBytes(key, bytesValue, version);
}
+ /**
+ * Create or update the value associated the specified key if the version
+ * checking is passed.
+ *
+ * The value of the key will be updated only if it's latest version equals the
+ * specified version argument.
+ * If the key doesn't exist, the version checking will be ignored, and key will
+ * be created with a new sequence number as id.
+ * It also could specify the version argument to -1 to ignore the version
+ * checking.
+ *
+ * If updating is performed, the version of the key increase by 1.
*
* {@link LedgerEditor} 以上一个区块作为数据编辑的起点;
@@ -52,7 +66,8 @@ public interface LedgerEditor {
*
*
*
- * 注:方法不解析、不执行交易中的操作;
+ * 注:方法不解析、不执行交易中的操作;
+ *
*
* @param txRequest 交易请求;
* @return
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerInitPermission.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerInitProposal.java
similarity index 92%
rename from source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerInitPermission.java
rename to source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerInitProposal.java
index 7ca9e15c..2baaacbd 100644
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerInitPermission.java
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerInitProposal.java
@@ -13,8 +13,8 @@ import com.jd.blockchain.ledger.LedgerInitOperation;
* @author huanghaiquan
*
*/
-@DataContract(code = DataCodes.METADATA_INIT_PERMISSION)
-public interface LedgerInitPermission {
+@DataContract(code = DataCodes.METADATA_INIT_PROPOSAL)
+public interface LedgerInitProposal {
/**
* 做出许可的参与方 ID;
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerInitPermissionData.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerInitProposalData.java
similarity index 68%
rename from source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerInitPermissionData.java
rename to source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerInitProposalData.java
index ead25a56..4fa95cb7 100644
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerInitPermissionData.java
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerInitProposalData.java
@@ -2,7 +2,7 @@ package com.jd.blockchain.ledger.core;
import com.jd.blockchain.crypto.SignatureDigest;
-public class LedgerInitPermissionData implements LedgerInitPermission {
+public class LedgerInitProposalData implements LedgerInitProposal {
private int participantId;
@@ -11,10 +11,11 @@ public class LedgerInitPermissionData implements LedgerInitPermission {
/**
* a private contructor for deserialize;
*/
- private LedgerInitPermissionData() {
+ @SuppressWarnings("unused")
+ private LedgerInitProposalData() {
}
- public LedgerInitPermissionData(int participantId, SignatureDigest initTxSignature) {
+ public LedgerInitProposalData(int participantId, SignatureDigest initTxSignature) {
this.participantId = participantId;
this.transactionSignature = initTxSignature;
}
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerInitializer.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerInitializer.java
new file mode 100644
index 00000000..c8c04712
--- /dev/null
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerInitializer.java
@@ -0,0 +1,316 @@
+package com.jd.blockchain.ledger.core;
+
+import com.jd.blockchain.crypto.HashDigest;
+import com.jd.blockchain.crypto.PrivKey;
+import com.jd.blockchain.crypto.SignatureDigest;
+import com.jd.blockchain.ledger.BlockchainIdentity;
+import com.jd.blockchain.ledger.BlockchainIdentityData;
+import com.jd.blockchain.ledger.BlockchainKeypair;
+import com.jd.blockchain.ledger.DigitalSignature;
+import com.jd.blockchain.ledger.LedgerAdminInfo;
+import com.jd.blockchain.ledger.LedgerAdminSettings;
+import com.jd.blockchain.ledger.LedgerBlock;
+import com.jd.blockchain.ledger.LedgerInitException;
+import com.jd.blockchain.ledger.LedgerInitOperation;
+import com.jd.blockchain.ledger.LedgerInitSetting;
+import com.jd.blockchain.ledger.ParticipantNode;
+import com.jd.blockchain.ledger.RoleInitSettings;
+import com.jd.blockchain.ledger.RolesConfigureOperation;
+import com.jd.blockchain.ledger.SecurityInitSettings;
+import com.jd.blockchain.ledger.TransactionBuilder;
+import com.jd.blockchain.ledger.TransactionContent;
+import com.jd.blockchain.ledger.TransactionRequest;
+import com.jd.blockchain.ledger.UserAuthInitSettings;
+import com.jd.blockchain.ledger.UserAuthorizeOperation;
+import com.jd.blockchain.ledger.UserRegisterOperation;
+import com.jd.blockchain.service.TransactionBatchResultHandle;
+import com.jd.blockchain.storage.service.KVStorageService;
+import com.jd.blockchain.transaction.SignatureUtils;
+import com.jd.blockchain.transaction.TxBuilder;
+import com.jd.blockchain.transaction.TxRequestBuilder;
+
+public class LedgerInitializer {
+
+ private static final FullPermissionedSecurityManager FULL_PERMISSION_SECURITY_MANAGER = new FullPermissionedSecurityManager();
+
+ private static final LedgerQuery EMPTY_LEDGER =new EmptyLedgerQuery();
+
+ private static final LedgerDataQuery EMPTY_LEDGER_DATA_QUERY = new EmptyLedgerDataset();
+
+ private static final OperationHandleRegisteration DEFAULT_OP_HANDLE_REG = new DefaultOperationHandleRegisteration();
+
+// private LedgerService EMPTY_LEDGERS = new LedgerManager();
+
+ private LedgerInitSetting initSetting;
+
+ private TransactionContent initTxContent;
+
+ private volatile LedgerBlock genesisBlock;
+
+ private volatile LedgerEditor ledgerEditor;
+
+ private volatile boolean committed = false;
+
+ private volatile boolean canceled = false;
+
+ private TransactionBatchResultHandle txResultsHandle;
+
+ /**
+ * 初始化生成的账本hash;
+ *
+ * “创世交易”按顺序由以下操作组成:
+ * If creating is performed, the version of the key initialize by 0.
+ *
+ * @param key The key of data;
+ * @param value The value of data;
+ * @param version The expected version of the key.
+ * @return The new version of the key.
+ * If the key is new created success, then return 0;
+ * If the key is updated success, then return the new version;
+ * If this operation fail by version checking or other reason, then
+ * return -1;
+ */
public long setBytes(Bytes key, byte[] value, long version) {
BytesValue bytesValue = BytesData.fromBytes(value);
return baseAccount.setBytes(key, bytesValue, version);
@@ -66,7 +135,7 @@ public class DataAccount implements AccountHeader, MerkleProvable {
* @return
*/
public long getDataVersion(String key) {
- return baseAccount.getKeyVersion(Bytes.fromString(key));
+ return baseAccount.getVersion(Bytes.fromString(key));
}
/**
@@ -77,7 +146,7 @@ public class DataAccount implements AccountHeader, MerkleProvable {
* @return
*/
public long getDataVersion(Bytes key) {
- return baseAccount.getKeyVersion(key);
+ return baseAccount.getVersion(key);
}
/**
@@ -121,6 +190,29 @@ public class DataAccount implements AccountHeader, MerkleProvable {
public BytesValue getBytes(Bytes key, long version) {
return baseAccount.getBytes(key, version);
}
+
+ /**
+ * @param key
+ * @param version
+ * @return
+ */
+ public KVDataEntry getDataEntry(String key, long version) {
+ return getDataEntry(Bytes.fromString(key), version);
+ }
+
+ /**
+ * @param key
+ * @param version
+ * @return
+ */
+ public KVDataEntry getDataEntry(Bytes key, long version) {
+ BytesValue value = baseAccount.getBytes(key, version);
+ if (value == null) {
+ return new KVDataObject(key.toUTF8String(), -1, null);
+ }else {
+ return new KVDataObject(key.toUTF8String(), version, value);
+ }
+ }
/**
* return the specified index's KVDataEntry;
@@ -131,7 +223,7 @@ public class DataAccount implements AccountHeader, MerkleProvable {
*/
public KVDataEntry[] getDataEntries(int fromIndex, int count) {
- if (getDataEntriesTotalCount() == 0 || count == 0) {
+ if (count == 0 || getDataEntriesTotalCount() == 0) {
return null;
}
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/DataAccountQuery.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/DataAccountQuery.java
new file mode 100644
index 00000000..c2bcb17d
--- /dev/null
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/DataAccountQuery.java
@@ -0,0 +1,5 @@
+package com.jd.blockchain.ledger.core;
+
+public interface DataAccountQuery extends AccountQuery
* 如果不存在,则返回 null;
@@ -63,16 +80,18 @@ public class DataAccountSet implements MerkleProvable, Transactional {
* @param address
* @return
*/
- public DataAccount getDataAccount(Bytes address) {
- BaseAccount accBase = accountSet.getAccount(address);
+ @Override
+ public DataAccount getAccount(Bytes address) {
+ MerkleAccount accBase = accountSet.getAccount(address);
if (accBase == null) {
return null;
}
return new DataAccount(accBase);
}
- public DataAccount getDataAccount(Bytes address, long version) {
- BaseAccount accBase = accountSet.getAccount(address, version);
+ @Override
+ public DataAccount getAccount(Bytes address, long version) {
+ MerkleAccount accBase = accountSet.getAccount(address, version);
return new DataAccount(accBase);
}
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/DefaultOperationHandleRegisteration.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/DefaultOperationHandleRegisteration.java
new file mode 100644
index 00000000..ae8ad40b
--- /dev/null
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/DefaultOperationHandleRegisteration.java
@@ -0,0 +1,122 @@
+package com.jd.blockchain.ledger.core;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.springframework.stereotype.Component;
+
+import com.jd.blockchain.ledger.LedgerException;
+import com.jd.blockchain.ledger.Operation;
+import com.jd.blockchain.ledger.core.handles.ContractCodeDeployOperationHandle;
+import com.jd.blockchain.ledger.core.handles.DataAccountKVSetOperationHandle;
+import com.jd.blockchain.ledger.core.handles.DataAccountRegisterOperationHandle;
+import com.jd.blockchain.ledger.core.handles.JVMContractEventSendOperationHandle;
+import com.jd.blockchain.ledger.core.handles.LedgerInitOperationHandle;
+import com.jd.blockchain.ledger.core.handles.ParticipantRegisterOperationHandle;
+import com.jd.blockchain.ledger.core.handles.ParticipantStateUpdateOperationHandle;
+import com.jd.blockchain.ledger.core.handles.RolesConfigureOperationHandle;
+import com.jd.blockchain.ledger.core.handles.UserAuthorizeOperationHandle;
+import com.jd.blockchain.ledger.core.handles.UserRegisterOperationHandle;
+
+@Component
+public class DefaultOperationHandleRegisteration implements OperationHandleRegisteration {
+
+ private static Map
- * 对 LedgerMetadata 修改的新配置不能立即生效,需要达成共识后,在下一次区块计算中才生效;
- */
- private LedgerSetting previousSetting;
-
- /**
- * 账本的参与节点;
- */
- private ParticipantDataSet participants;
-
- // /**
- // * 账本的全局权限设置;
- // */
- // private PrivilegeDataSet privileges;
-
- private ExPolicyKVStorage settingsStorage;
-
- private HashDigest adminAccountHash;
-
- private boolean readonly;
-
- private boolean updated;
-
- public HashDigest getHash() {
- return adminAccountHash;
- }
-
- public boolean isReadonly() {
- return readonly;
- }
-
- /**
- * 初始化账本的管理账户;
- *
- *
- *
- * 只在新建账本时调用此方法;
- *
- * @param ledgerSeed
- * @param setting
- * @param partiList
- * @param exPolicyStorage
- * @param versioningStorage
- */
- public LedgerAdminAccount(LedgerInitSetting initSetting, String keyPrefix, ExPolicyKVStorage exPolicyStorage,
- VersioningKVStorage versioningStorage) {
- this.metaPrefix = Bytes.fromString(keyPrefix + LEDGER_META_PREFIX);
- this.privilegePrefix = Bytes.fromString(keyPrefix + LEDGER_PRIVILEGE_PREFIX);
-
- ParticipantNode[] parties = initSetting.getConsensusParticipants();
- if (parties.length == 0) {
- throw new LedgerException("No participant!");
- }
-
- // 检查参与者列表是否已经按照 id 升序排列,并且 id 不冲突;
- // 注:参与者的 id 要求从 0 开始编号,顺序依次递增,不允许跳空;
- for (int i = 0; i < parties.length; i++) {
- // if (parties[i].getAddress() != i) {
- // throw new LedgerException("The id of participant isn't match the order of the
- // participant list!");
- // }
- }
-
- // 初始化元数据;
- this.metadata = new LedgerMetadataImpl();
- this.metadata.setSeed(initSetting.getLedgerSeed());
- // 新配置;
- this.metadata.setting = new LedgerConfiguration(initSetting.getConsensusProvider(),
- initSetting.getConsensusSettings(), initSetting.getCryptoSetting());
- this.previousSetting = new LedgerConfiguration(initSetting.getConsensusProvider(),
- initSetting.getConsensusSettings(), initSetting.getCryptoSetting());
- this.adminAccountHash = null;
-
- // 基于原配置初始化参与者列表;
- String partiPrefix = keyPrefix + LEDGER_PARTICIPANT_PREFIX;
- this.participants = new ParticipantDataSet(previousSetting.getCryptoSetting(), partiPrefix, exPolicyStorage,
- versioningStorage);
-
- for (ParticipantNode p : parties) {
- this.participants.addConsensusParticipant(p);
- }
-
- // 初始化其它属性;
- this.settingsStorage = exPolicyStorage;
- this.readonly = false;
- }
-
- public LedgerAdminAccount(HashDigest adminAccountHash, String keyPrefix, ExPolicyKVStorage kvStorage,
- VersioningKVStorage versioningKVStorage, boolean readonly) {
- this.metaPrefix = Bytes.fromString(keyPrefix + LEDGER_META_PREFIX);
- this.privilegePrefix = Bytes.fromString(keyPrefix + LEDGER_PRIVILEGE_PREFIX);
- this.settingsStorage = kvStorage;
- this.readonly = readonly;
- this.origMetadata = loadAndVerifySettings(adminAccountHash);
- this.metadata = new LedgerMetadataImpl(origMetadata);
- // 复制记录一份配置作为上一个区块的原始配置,该实例仅供读取,不做修改,也不会回写到存储;
- this.previousSetting = new LedgerConfiguration(metadata.getSetting());
- this.adminAccountHash = adminAccountHash;
- // this.privileges = new PrivilegeDataSet(metadata.getPrivilegesHash(),
- // metadata.getSetting().getCryptoSetting(),
- // PrefixAppender.prefix(LEDGER_PRIVILEGE_PREFIX, kvStorage),
- // PrefixAppender.prefix(LEDGER_PRIVILEGE_PREFIX, versioningKVStorage),
- // readonly);
-
- // this.participants = new ParticipantDataSet(metadata.getParticipantsHash(),
- // previousSetting.getCryptoSetting(),
- // PrefixAppender.prefix(LEDGER_PARTICIPANT_PREFIX, kvStorage),
- // PrefixAppender.prefix(LEDGER_PARTICIPANT_PREFIX, versioningKVStorage),
- // readonly);
- String partiPrefix = keyPrefix + LEDGER_PARTICIPANT_PREFIX;
- this.participants = new ParticipantDataSet(metadata.getParticipantsHash(), previousSetting.getCryptoSetting(),
- partiPrefix, kvStorage, versioningKVStorage, readonly);
- }
-
- private LedgerMetadata loadAndVerifySettings(HashDigest adminAccountHash) {
- // String base58Hash = adminAccountHash.toBase58();
- // String key = encodeMetadataKey(base58Hash);
- Bytes key = encodeMetadataKey(adminAccountHash);
- byte[] bytes = settingsStorage.get(key);
- HashFunction hashFunc = Crypto.getHashFunction(adminAccountHash.getAlgorithm());
- if (!hashFunc.verify(adminAccountHash, bytes)) {
- LOGGER.error("The hash verification of ledger settings fail! --[HASH=" + key + "]");
- throw new LedgerException("The hash verification of ledger settings fail!");
- }
- return deserializeMetadata(bytes);
- }
-
- private Bytes encodeMetadataKey(HashDigest metadataHash) {
- // return LEDGER_META_PREFIX + metadataHash;
- // return metaPrefix + metadataHash;
- return metaPrefix.concat(metadataHash);
- }
-
- /*
- * (non-Javadoc)
- *
- * @see com.jd.blockchain.ledger.core.LedgerAdministration#getMetadata()
- */
- @Override
- public LedgerMetadata getMetadata() {
- return metadata;
- }
-
- /**
- * 返回原来的账本配置;
- *
- *
- * 此方法总是返回从上一个区块加载的账本配置,即时调用 {@link #setLedgerSetting(LedgerSetting)} 做出了新的更改;
- *
- * @return
- */
- public LedgerSetting getPreviousSetting() {
- return previousSetting;
- }
-
- /**
- * 返回当前设置的账本配置;
- *
- * @return
- */
- public LedgerSetting getSetting() {
- return metadata.getSetting();
- }
-
- /**
- * 更新账本配置;
- *
- * @param ledgerSetting
- */
- public void setLedgerSetting(LedgerSetting ledgerSetting) {
- if (readonly) {
- throw new IllegalArgumentException("This merkle dataset is readonly!");
- }
- metadata.setSetting(ledgerSetting);
- }
-
- @Override
- public long getParticipantCount() {
- return participants.getParticipantCount();
- }
-
- // /*
- // * (non-Javadoc)
- // *
- // * @see
- // *
- // com.jd.blockchain.ledger.core.LedgerAdministration#getParticipant(java.lang.
- // * String)
- // */
- // @Override
- // public ParticipantNode getParticipant(int id) {
- // return participants.getParticipant(id);
- // }
-
- @Override
- public ParticipantNode[] getParticipants() {
- return participants.getParticipants();
- }
-
- /**
- * 加入新的参与方; 如果指定的参与方已经存在,则引发 LedgerException 异常;
- *
- * @param participant
- */
- public void addParticipant(ParticipantNode participant) {
- participants.addConsensusParticipant(participant);
- }
-
- @Override
- public boolean isUpdated() {
- return updated || participants.isUpdated();
- }
-
- @Override
- public void commit() {
- if (!isUpdated()) {
- return;
- }
- participants.commit();
-
- metadata.setParticipantsHash(participants.getRootHash());
-
- // 基于之前的密码配置来计算元数据的哈希;
- byte[] metadataBytes = serializeMetadata(metadata);
- HashFunction hashFunc = Crypto
- .getHashFunction(previousSetting.getCryptoSetting().getHashAlgorithm());
- HashDigest metadataHash = hashFunc.hash(metadataBytes);
- if (adminAccountHash == null || !adminAccountHash.equals(metadataHash)) {
- // update modify;
- // String base58MetadataHash = metadataHash.toBase58();
- // String metadataKey = encodeMetadataKey(base58MetadataHash);
- Bytes metadataKey = encodeMetadataKey(metadataHash);
-
- boolean nx = settingsStorage.set(metadataKey, metadataBytes, ExPolicy.NOT_EXISTING);
- if (!nx) {
- // 有可能发生了并发写入冲突,不同的节点都向同一个存储服务器上写入数据;
- // throw new LedgerException(
- // "Ledger metadata already exist! --[LedgerMetadataHash=" + base58MetadataHash
- // + "]");
- // LOGGER.warn("Ledger metadata already exist! --[MetadataHash=" +
- // base58MetadataHash + "]");
- }
-
- adminAccountHash = metadataHash;
- }
-
- updated = false;
- }
-
- private LedgerMetadata deserializeMetadata(byte[] bytes) {
- return BinaryProtocol.decode(bytes);
- }
-
- private byte[] serializeMetadata(LedgerMetadataImpl config) {
- return BinaryProtocol.encode(config, LedgerMetadata.class);
- }
-
- @Override
- public void cancel() {
- if (!isUpdated()) {
- return;
- }
- participants.cancel();
- metadata = new LedgerMetadataImpl(origMetadata);
- }
-
- public static class LedgerMetadataImpl implements LedgerMetadata {
-
- private byte[] seed;
-
- private LedgerSetting setting;
-
- private HashDigest participantsHash;
-
- public LedgerMetadataImpl() {
- }
-
- public LedgerMetadataImpl(LedgerMetadata metadata) {
- this.seed = metadata.getSeed();
- this.setting = metadata.getSetting();
- this.participantsHash = metadata.getParticipantsHash();
- }
-
- @Override
- public byte[] getSeed() {
- return seed;
- }
-
- @Override
- public LedgerSetting getSetting() {
- return setting;
- }
-
- @Override
- public HashDigest getParticipantsHash() {
- return participantsHash;
- }
-
- public void setSeed(byte[] seed) {
- this.seed = seed;
- }
-
- public void setSetting(LedgerSetting setting) {
- // copy a new instance;
- this.setting = new LedgerConfiguration(setting);
- }
-
- public void setParticipantsHash(HashDigest participantsHash) {
- this.participantsHash = participantsHash;
- }
- }
-
-}
\ No newline at end of file
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerAdminDataQuery.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerAdminDataQuery.java
new file mode 100644
index 00000000..623a47b1
--- /dev/null
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerAdminDataQuery.java
@@ -0,0 +1,12 @@
+package com.jd.blockchain.ledger.core;
+
+import com.jd.blockchain.ledger.LedgerAdminSettings;
+import com.jd.blockchain.ledger.ParticipantDataQuery;
+
+public interface LedgerAdminDataQuery {
+
+ LedgerAdminSettings getAdminInfo();
+
+ ParticipantDataQuery getParticipantDataset();
+
+}
\ No newline at end of file
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerAdminDataset.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerAdminDataset.java
new file mode 100644
index 00000000..dfd06a1e
--- /dev/null
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerAdminDataset.java
@@ -0,0 +1,481 @@
+package com.jd.blockchain.ledger.core;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.jd.blockchain.binaryproto.BinaryProtocol;
+import com.jd.blockchain.binaryproto.DataContractRegistry;
+import com.jd.blockchain.crypto.Crypto;
+import com.jd.blockchain.crypto.HashDigest;
+import com.jd.blockchain.crypto.HashFunction;
+import com.jd.blockchain.ledger.LedgerAdminSettings;
+import com.jd.blockchain.ledger.LedgerException;
+import com.jd.blockchain.ledger.LedgerInitSetting;
+import com.jd.blockchain.ledger.LedgerMetadata;
+import com.jd.blockchain.ledger.LedgerMetadata_V2;
+import com.jd.blockchain.ledger.LedgerSettings;
+import com.jd.blockchain.ledger.ParticipantNode;
+import com.jd.blockchain.ledger.RolePrivilegeSettings;
+import com.jd.blockchain.ledger.UserAuthorizationSettings;
+import com.jd.blockchain.storage.service.ExPolicyKVStorage;
+import com.jd.blockchain.storage.service.ExPolicyKVStorage.ExPolicy;
+import com.jd.blockchain.storage.service.VersioningKVStorage;
+import com.jd.blockchain.utils.Bytes;
+import com.jd.blockchain.utils.Transactional;
+
+public class LedgerAdminDataset implements Transactional, LedgerAdminDataQuery, LedgerAdminSettings {
+
+ static {
+ DataContractRegistry.register(LedgerMetadata.class);
+ DataContractRegistry.register(LedgerMetadata_V2.class);
+ }
+
+ private static Logger LOGGER = LoggerFactory.getLogger(LedgerAdminDataset.class);
+
+ public static final String LEDGER_META_PREFIX = "MTA" + LedgerConsts.KEY_SEPERATOR;
+ public static final String LEDGER_PARTICIPANT_PREFIX = "PAR" + LedgerConsts.KEY_SEPERATOR;
+ public static final String LEDGER_SETTING_PREFIX = "SET" + LedgerConsts.KEY_SEPERATOR;
+ public static final String ROLE_PRIVILEGE_PREFIX = "RPV" + LedgerConsts.KEY_SEPERATOR;
+ public static final String USER_ROLE_PREFIX = "URO" + LedgerConsts.KEY_SEPERATOR;
+
+ private final Bytes metaPrefix;
+ private final Bytes settingPrefix;
+
+ private LedgerMetadata_V2 origMetadata;
+
+ private LedgerMetadataInfo metadata;
+
+ /**
+ * 原来的账本设置;
+ *
+ *
+ * 对 LedgerMetadata 修改的新配置不能立即生效,需要达成共识后,在下一次区块计算中才生效;
+ */
+ private LedgerSettings previousSettings;
+
+ private HashDigest previousSettingHash;
+
+ /**
+ * 账本的参与节点;
+ */
+ private ParticipantDataset participants;
+
+ /**
+ * “角色-权限”数据集;
+ */
+ private RolePrivilegeDataset rolePrivileges;
+
+ /**
+ * “用户-角色”数据集;
+ */
+ private UserRoleDataset userRoles;
+
+ /**
+ * 账本参数配置;
+ */
+ private LedgerSettings settings;
+
+ private ExPolicyKVStorage storage;
+
+ private HashDigest adminDataHash;
+
+ private boolean readonly;
+
+ private boolean updated;
+
+ public HashDigest getHash() {
+ return adminDataHash;
+ }
+
+ public boolean isReadonly() {
+ return readonly;
+ }
+
+ void setReadonly() {
+ this.readonly = true;
+ }
+
+ public LedgerSettings getPreviousSetting() {
+ return previousSettings;
+ }
+
+ @Override
+ public RolePrivilegeSettings getRolePrivileges() {
+ return rolePrivileges;
+ }
+
+ @Override
+ public UserAuthorizationSettings getAuthorizations() {
+ return userRoles;
+ }
+
+ @Override
+ public LedgerAdminSettings getAdminInfo() {
+ return this;
+ }
+
+ /**
+ * 初始化账本的管理账户;
+ *
+ *
+ *
+ * 只在新建账本时调用此方法;
+ *
+ * @param ledgerSeed
+ * @param settings
+ * @param partiList
+ * @param exPolicyStorage
+ * @param versioningStorage
+ */
+ public LedgerAdminDataset(LedgerInitSetting initSetting, String keyPrefix, ExPolicyKVStorage exPolicyStorage,
+ VersioningKVStorage versioningStorage) {
+ this.metaPrefix = Bytes.fromString(keyPrefix + LEDGER_META_PREFIX);
+ this.settingPrefix = Bytes.fromString(keyPrefix + LEDGER_SETTING_PREFIX);
+
+ ParticipantNode[] parties = initSetting.getConsensusParticipants();
+ if (parties.length == 0) {
+ throw new LedgerException("No participant!");
+ }
+
+ // 初始化元数据;
+ this.metadata = new LedgerMetadataInfo();
+ this.metadata.setSeed(initSetting.getLedgerSeed());
+ // 新配置;
+ this.settings = new LedgerConfiguration(initSetting.getConsensusProvider(), initSetting.getConsensusSettings(),
+ initSetting.getCryptoSetting());
+ this.previousSettings = new LedgerConfiguration(settings);
+ this.previousSettingHash = null;
+ this.adminDataHash = null;
+
+ // 基于原配置初始化参与者列表;
+ String partiPrefix = keyPrefix + LEDGER_PARTICIPANT_PREFIX;
+ this.participants = new ParticipantDataset(previousSettings.getCryptoSetting(), partiPrefix, exPolicyStorage,
+ versioningStorage);
+
+ for (ParticipantNode p : parties) {
+ this.participants.addConsensusParticipant(p);
+ }
+
+ String rolePrivilegePrefix = keyPrefix + ROLE_PRIVILEGE_PREFIX;
+ this.rolePrivileges = new RolePrivilegeDataset(this.settings.getCryptoSetting(), rolePrivilegePrefix,
+ exPolicyStorage, versioningStorage);
+
+ String userRolePrefix = keyPrefix + USER_ROLE_PREFIX;
+ this.userRoles = new UserRoleDataset(this.settings.getCryptoSetting(), userRolePrefix, exPolicyStorage,
+ versioningStorage);
+
+ // 初始化其它属性;
+ this.storage = exPolicyStorage;
+ this.readonly = false;
+ }
+
+ public LedgerAdminDataset(HashDigest adminAccountHash, String keyPrefix, ExPolicyKVStorage kvStorage,
+ VersioningKVStorage versioningKVStorage, boolean readonly) {
+ this.metaPrefix = Bytes.fromString(keyPrefix + LEDGER_META_PREFIX);
+ this.settingPrefix = Bytes.fromString(keyPrefix + LEDGER_SETTING_PREFIX);
+ this.storage = kvStorage;
+ this.readonly = readonly;
+ this.origMetadata = loadAndVerifyMetadata(adminAccountHash);
+ this.metadata = new LedgerMetadataInfo(origMetadata);
+ this.settings = loadAndVerifySettings(metadata.getSettingsHash());
+ // 复制记录一份配置作为上一个区块的原始配置,该实例仅供读取,不做修改,也不会回写到存储;
+ this.previousSettings = new LedgerConfiguration(settings);
+ this.previousSettingHash = metadata.getSettingsHash();
+ this.adminDataHash = adminAccountHash;
+
+ String partiPrefix = keyPrefix + LEDGER_PARTICIPANT_PREFIX;
+ this.participants = new ParticipantDataset(metadata.getParticipantsHash(), previousSettings.getCryptoSetting(),
+ partiPrefix, kvStorage, versioningKVStorage, readonly);
+
+ String rolePrivilegePrefix = keyPrefix + ROLE_PRIVILEGE_PREFIX;
+ this.rolePrivileges = new RolePrivilegeDataset(metadata.getRolePrivilegesHash(),
+ previousSettings.getCryptoSetting(), rolePrivilegePrefix, kvStorage, versioningKVStorage, readonly);
+
+ String userRolePrefix = keyPrefix + USER_ROLE_PREFIX;
+ this.userRoles = new UserRoleDataset(metadata.getUserRolesHash(), previousSettings.getCryptoSetting(),
+ userRolePrefix, kvStorage, versioningKVStorage, readonly);
+ }
+
+ private LedgerSettings loadAndVerifySettings(HashDigest settingsHash) {
+ if (settingsHash == null) {
+ return null;
+ }
+ Bytes key = encodeSettingsKey(settingsHash);
+ byte[] bytes = storage.get(key);
+ HashFunction hashFunc = Crypto.getHashFunction(settingsHash.getAlgorithm());
+ if (!hashFunc.verify(settingsHash, bytes)) {
+ String errorMsg = "Verification of the hash for ledger setting failed! --[HASH=" + key + "]";
+ LOGGER.error(errorMsg);
+ throw new LedgerException(errorMsg);
+ }
+ return deserializeSettings(bytes);
+ }
+
+ private LedgerSettings deserializeSettings(byte[] bytes) {
+ return BinaryProtocol.decode(bytes);
+ }
+
+ private byte[] serializeSetting(LedgerSettings setting) {
+ return BinaryProtocol.encode(setting, LedgerSettings.class);
+ }
+
+ private LedgerMetadata_V2 loadAndVerifyMetadata(HashDigest adminAccountHash) {
+ Bytes key = encodeMetadataKey(adminAccountHash);
+ byte[] bytes = storage.get(key);
+ HashFunction hashFunc = Crypto.getHashFunction(adminAccountHash.getAlgorithm());
+ if (!hashFunc.verify(adminAccountHash, bytes)) {
+ String errorMsg = "Verification of the hash for ledger metadata failed! --[HASH=" + key + "]";
+ LOGGER.error(errorMsg);
+ throw new LedgerException(errorMsg);
+ }
+ return deserializeMetadata(bytes);
+ }
+
+ private Bytes encodeSettingsKey(HashDigest settingsHash) {
+ return settingPrefix.concat(settingsHash);
+ }
+
+ private Bytes encodeMetadataKey(HashDigest metadataHash) {
+ // return LEDGER_META_PREFIX + metadataHash;
+ // return metaPrefix + metadataHash;
+ return metaPrefix.concat(metadataHash);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.jd.blockchain.ledger.core.LedgerAdministration#getMetadata()
+ */
+ @Override
+ public LedgerMetadata_V2 getMetadata() {
+ return metadata;
+ }
+
+// /**
+// * 返回原来的账本配置;
+// *
+// *
+// * 此方法总是返回从上一个区块加载的账本配置,即时调用 {@link #setLedgerSetting(LedgerSettings)} 做出了新的更改;
+// *
+// * @return
+// */
+// public LedgerSettings getPreviousSetting() {
+// return previousSettings;
+// }
+
+ /**
+ * 返回当前设置的账本配置;
+ *
+ * @return
+ */
+
+ @Override
+ public LedgerSettings getSettings() {
+ return settings;
+ }
+
+ /**
+ * 更新账本配置;
+ *
+ * @param ledgerSetting
+ */
+ public void setLedgerSetting(LedgerSettings ledgerSetting) {
+ if (readonly) {
+ throw new IllegalArgumentException("This merkle dataset is readonly!");
+ }
+ settings = ledgerSetting;
+ updated = true;
+ }
+
+ @Override
+ public long getParticipantCount() {
+ return participants.getParticipantCount();
+ }
+
+ @Override
+ public ParticipantNode[] getParticipants() {
+ return participants.getParticipants();
+ }
+
+ @Override
+ public ParticipantDataset getParticipantDataset() {
+ return participants;
+ }
+
+ /**
+ * 加入新的参与方; 如果指定的参与方已经存在,则引发 LedgerException 异常;
+ *
+ * @param participant
+ */
+ public void addParticipant(ParticipantNode participant) {
+ participants.addConsensusParticipant(participant);
+ }
+
+
+ /**
+ * 更新参与方的状态参数;
+ *
+ * @param participant
+ */
+ public void updateParticipant(ParticipantNode participant) {
+ participants.updateConsensusParticipant(participant);
+ }
+
+ @Override
+ public boolean isUpdated() {
+ return updated || participants.isUpdated() || rolePrivileges.isUpdated() || userRoles.isUpdated();
+ }
+
+ @Override
+ public void commit() {
+ if (!isUpdated()) {
+ return;
+ }
+ // 计算并更新参与方集合的根哈希;
+ participants.commit();
+ metadata.setParticipantsHash(participants.getRootHash());
+
+ // 计算并更新角色权限集合的根哈希;
+ rolePrivileges.commit();
+ metadata.setRolePrivilegesHash(rolePrivileges.getRootHash());
+
+ // 计算并更新用户角色授权集合的根哈希;
+ userRoles.commit();
+ metadata.setUserRolesHash(userRoles.getRootHash());
+
+ // 当前区块上下文的密码参数设置的哈希函数;
+ HashFunction hashFunc = Crypto.getHashFunction(previousSettings.getCryptoSetting().getHashAlgorithm());
+
+ // 计算并更新参数配置的哈希;
+ if (settings == null) {
+ throw new LedgerException("Missing ledger settings!");
+ }
+ byte[] settingsBytes = serializeSetting(settings);
+ HashDigest settingsHash = hashFunc.hash(settingsBytes);
+ metadata.setSettingsHash(settingsHash);
+ if (previousSettingHash == null || !previousSettingHash.equals(settingsHash)) {
+ Bytes settingsKey = encodeSettingsKey(settingsHash);
+ boolean nx = storage.set(settingsKey, settingsBytes, ExPolicy.NOT_EXISTING);
+ if (!nx) {
+ String base58MetadataHash = settingsHash.toBase58();
+ // 有可能发生了并发写入冲突,不同的节点都向同一个存储服务器上写入数据;
+ String errMsg = "Ledger metadata already exist! --[MetadataHash=" + base58MetadataHash + "]";
+ LOGGER.warn(errMsg);
+ throw new LedgerException(errMsg);
+ }
+ }
+
+ // 基于之前的密码配置来计算元数据的哈希;
+ byte[] metadataBytes = serializeMetadata(metadata);
+
+ HashDigest metadataHash = hashFunc.hash(metadataBytes);
+ if (adminDataHash == null || !adminDataHash.equals(metadataHash)) {
+ // update modify;
+ // String base58MetadataHash = metadataHash.toBase58();
+ // String metadataKey = encodeMetadataKey(base58MetadataHash);
+ Bytes metadataKey = encodeMetadataKey(metadataHash);
+
+ boolean nx = storage.set(metadataKey, metadataBytes, ExPolicy.NOT_EXISTING);
+ if (!nx) {
+ String base58MetadataHash = metadataHash.toBase58();
+ // 有可能发生了并发写入冲突,不同的节点都向同一个存储服务器上写入数据;
+ String errMsg = "Ledger metadata already exist! --[MetadataHash=" + base58MetadataHash + "]";
+ LOGGER.warn(errMsg);
+ throw new LedgerException(errMsg);
+ }
+
+ adminDataHash = metadataHash;
+ }
+
+ updated = false;
+ }
+
+ private LedgerMetadata_V2 deserializeMetadata(byte[] bytes) {
+ return BinaryProtocol.decode(bytes);
+ }
+
+ private byte[] serializeMetadata(LedgerMetadataInfo config) {
+ return BinaryProtocol.encode(config, LedgerMetadata_V2.class);
+ }
+
+ @Override
+ public void cancel() {
+ if (!isUpdated()) {
+ return;
+ }
+ participants.cancel();
+ metadata =origMetadata == null ? new LedgerMetadataInfo() : new LedgerMetadataInfo(origMetadata);
+ }
+
+ public static class LedgerMetadataInfo implements LedgerMetadata_V2 {
+
+ private byte[] seed;
+
+// private LedgerSetting setting;
+
+ private HashDigest participantsHash;
+
+ private HashDigest settingsHash;
+
+ private HashDigest rolePrivilegesHash;
+
+ private HashDigest userRolesHash;
+
+ public LedgerMetadataInfo() {
+ }
+
+ public LedgerMetadataInfo(LedgerMetadata_V2 metadata) {
+ this.seed = metadata.getSeed();
+ this.participantsHash = metadata.getParticipantsHash();
+ this.settingsHash = metadata.getSettingsHash();
+ this.rolePrivilegesHash = metadata.getRolePrivilegesHash();
+ this.userRolesHash = metadata.getUserRolesHash();
+ }
+
+ @Override
+ public byte[] getSeed() {
+ return seed;
+ }
+
+ @Override
+ public HashDigest getSettingsHash() {
+ return settingsHash;
+ }
+
+ @Override
+ public HashDigest getParticipantsHash() {
+ return participantsHash;
+ }
+
+ @Override
+ public HashDigest getRolePrivilegesHash() {
+ return rolePrivilegesHash;
+ }
+
+ @Override
+ public HashDigest getUserRolesHash() {
+ return userRolesHash;
+ }
+
+ public void setSeed(byte[] seed) {
+ this.seed = seed;
+ }
+
+ public void setSettingsHash(HashDigest settingHash) {
+ this.settingsHash = settingHash;
+ }
+
+ public void setParticipantsHash(HashDigest participantsHash) {
+ this.participantsHash = participantsHash;
+ }
+
+ public void setRolePrivilegesHash(HashDigest rolePrivilegesHash) {
+ this.rolePrivilegesHash = rolePrivilegesHash;
+ }
+
+ public void setUserRolesHash(HashDigest userRolesHash) {
+ this.userRolesHash = userRolesHash;
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerAdminInfoData.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerAdminInfoData.java
new file mode 100644
index 00000000..a0a74190
--- /dev/null
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerAdminInfoData.java
@@ -0,0 +1,92 @@
+package com.jd.blockchain.ledger.core;
+
+import com.jd.blockchain.ledger.*;
+
+/**
+ * @author shaozhuguang
+ * @date 2019-09-16
+ *
+ * LedgerAdminInfo的独立实现类,主要用于页面展示,区分 {@link LedgerAdminDataset}
+ */
+public class LedgerAdminInfoData implements LedgerAdminInfo {
+
+ /**
+ * 元数据
+ */
+ private LedgerMetadata_V2 metadata;
+
+ /**
+ * 账本配置
+ *
+ */
+ private LedgerSettings ledgerSettings;
+
+ /**
+ * 参与方数量
+ *
+ */
+ private long participantCount;
+
+ /**
+ * 参与方
+ *
+ */
+ private ParticipantNode[] participantNodes;
+
+ /**
+ * 包装构造方法
+ *
+ * @param ledgerAdminInfo
+ */
+ public LedgerAdminInfoData(LedgerAdminInfo ledgerAdminInfo) {
+ this(ledgerAdminInfo.getMetadata(), ledgerAdminInfo.getSettings(),
+ ledgerAdminInfo.getParticipantCount(), ledgerAdminInfo.getParticipants());
+ }
+
+ public LedgerAdminInfoData(LedgerMetadata_V2 metadata, LedgerSettings ledgerSettings, long participantCount, ParticipantNode[] participantNodes) {
+ this.metadata = metadata;
+ this.ledgerSettings = ledgerSettings;
+ this.participantCount = participantCount;
+ this.participantNodes = participantNodes;
+ }
+
+ /**
+ * 返回元数据配置信息
+ *
+ * @return
+ */
+ @Override
+ public LedgerMetadata_V2 getMetadata() {
+ return this.metadata;
+ }
+
+ /**
+ * 返回当前设置的账本配置;
+ *
+ * @return
+ */
+ @Override
+ public LedgerSettings getSettings() {
+ return this.ledgerSettings;
+ }
+
+ /**
+ * 返回当前参与方的数量
+ *
+ * @return
+ */
+ @Override
+ public long getParticipantCount() {
+ return this.participantCount;
+ }
+
+ /**
+ * 返回当前参与方列表
+ *
+ * @return
+ */
+ @Override
+ public ParticipantNode[] getParticipants() {
+ return this.participantNodes;
+ }
+}
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerAdminPrivilege.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerAdminPrivilege.java
deleted file mode 100644
index b436b5da..00000000
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerAdminPrivilege.java
+++ /dev/null
@@ -1,5 +0,0 @@
-package com.jd.blockchain.ledger.core;
-
-public enum LedgerAdminPrivilege {
-
-}
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerAdministration.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerAdministration.java
deleted file mode 100644
index cc09138f..00000000
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerAdministration.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package com.jd.blockchain.ledger.core;
-
-import com.jd.blockchain.ledger.LedgerMetadata;
-import com.jd.blockchain.ledger.ParticipantNode;
-
-public interface LedgerAdministration {
-
- LedgerMetadata getMetadata();
-
- long getParticipantCount();
-
-// ParticipantNode getParticipant(int id);
-
- ParticipantNode[] getParticipants();
-
-}
\ No newline at end of file
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerBlockData.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerBlockData.java
similarity index 98%
rename from source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerBlockData.java
rename to source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerBlockData.java
index 1e8865b7..3c667ebe 100644
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerBlockData.java
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerBlockData.java
@@ -1,4 +1,4 @@
-package com.jd.blockchain.ledger.core.impl;
+package com.jd.blockchain.ledger.core;
import com.jd.blockchain.binaryproto.DataContractRegistry;
import com.jd.blockchain.crypto.HashDigest;
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerConfiguration.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerConfiguration.java
index 5605003c..e727c5ad 100644
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerConfiguration.java
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerConfiguration.java
@@ -1,10 +1,10 @@
package com.jd.blockchain.ledger.core;
import com.jd.blockchain.ledger.CryptoSetting;
-import com.jd.blockchain.ledger.LedgerSetting;
+import com.jd.blockchain.ledger.LedgerSettings;
import com.jd.blockchain.utils.Bytes;
-public class LedgerConfiguration implements LedgerSetting {
+public class LedgerConfiguration implements LedgerSettings {
private String consensusProvider;
@@ -16,7 +16,7 @@ public class LedgerConfiguration implements LedgerSetting {
this.cryptoSetting = new CryptoConfig();
}
- public LedgerConfiguration(LedgerSetting origSetting) {
+ public LedgerConfiguration(LedgerSettings origSetting) {
if (origSetting != null) {
this.consensusProvider = origSetting.getConsensusProvider();
this.consensusSetting = origSetting.getConsensusSetting();
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerDataQuery.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerDataQuery.java
new file mode 100644
index 00000000..df70d0c0
--- /dev/null
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerDataQuery.java
@@ -0,0 +1,19 @@
+package com.jd.blockchain.ledger.core;
+
+/**
+ * {@link LedgerDataset} 表示账本在某一个区块上的数据集合;
+ *
+ * @author huanghaiquan
+ *
+ */
+public interface LedgerDataQuery{
+
+ LedgerAdminDataQuery getAdminDataset();
+
+ UserAccountQuery getUserAccountSet();
+
+ DataAccountQuery getDataAccountSet();
+
+ ContractAccountQuery getContractAccountset();
+
+}
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerDataSet.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerDataSet.java
deleted file mode 100644
index 40f63da6..00000000
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerDataSet.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package com.jd.blockchain.ledger.core;
-
-/**
- * {@link LedgerDataSet} 表示账本在某一个区块上的数据集合;
- *
- * @author huanghaiquan
- *
- */
-public interface LedgerDataSet{
-
- boolean isReadonly();
-
- LedgerAdminAccount getAdminAccount();
-
- UserAccountSet getUserAccountSet();
-
- DataAccountSet getDataAccountSet();
-
- ContractAccountSet getContractAccountSet();
-
-}
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerDataSetImpl.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerDataset.java
similarity index 62%
rename from source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerDataSetImpl.java
rename to source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerDataset.java
index 4ec9d657..9f840d35 100644
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerDataSetImpl.java
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerDataset.java
@@ -1,33 +1,31 @@
-package com.jd.blockchain.ledger.core.impl;
+package com.jd.blockchain.ledger.core;
-import com.jd.blockchain.ledger.core.*;
import com.jd.blockchain.utils.Transactional;
-public class LedgerDataSetImpl implements LedgerDataSet, Transactional {
+public class LedgerDataset implements LedgerDataQuery, Transactional {
- private LedgerAdminAccount adminAccount;
+ private LedgerAdminDataset adminDataset;
private UserAccountSet userAccountSet;
private DataAccountSet dataAccountSet;
private ContractAccountSet contractAccountSet;
-
- private boolean readonly;
+ private boolean readonly;
/**
* Create new block;
+ *
* @param adminAccount
* @param userAccountSet
* @param dataAccountSet
* @param contractAccountSet
* @param readonly
*/
- public LedgerDataSetImpl(LedgerAdminAccount adminAccount,
- UserAccountSet userAccountSet, DataAccountSet dataAccountSet, ContractAccountSet contractAccountSet,
- boolean readonly) {
- this.adminAccount = adminAccount;
+ public LedgerDataset(LedgerAdminDataset adminAccount, UserAccountSet userAccountSet,
+ DataAccountSet dataAccountSet, ContractAccountSet contractAccountSet, boolean readonly) {
+ this.adminDataset = adminAccount;
this.userAccountSet = userAccountSet;
this.dataAccountSet = dataAccountSet;
this.contractAccountSet = contractAccountSet;
@@ -36,8 +34,8 @@ public class LedgerDataSetImpl implements LedgerDataSet, Transactional {
}
@Override
- public LedgerAdminAccount getAdminAccount() {
- return adminAccount;
+ public LedgerAdminDataset getAdminDataset() {
+ return adminDataset;
}
@Override
@@ -51,13 +49,13 @@ public class LedgerDataSetImpl implements LedgerDataSet, Transactional {
}
@Override
- public ContractAccountSet getContractAccountSet() {
+ public ContractAccountSet getContractAccountset() {
return contractAccountSet;
}
@Override
public boolean isUpdated() {
- return adminAccount.isUpdated() || userAccountSet.isUpdated() || dataAccountSet.isUpdated()
+ return adminDataset.isUpdated() || userAccountSet.isUpdated() || dataAccountSet.isUpdated()
|| contractAccountSet.isUpdated();
}
@@ -70,7 +68,7 @@ public class LedgerDataSetImpl implements LedgerDataSet, Transactional {
return;
}
- adminAccount.commit();
+ adminDataset.commit();
userAccountSet.commit();
dataAccountSet.commit();
contractAccountSet.commit();
@@ -78,15 +76,22 @@ public class LedgerDataSetImpl implements LedgerDataSet, Transactional {
@Override
public void cancel() {
- adminAccount.cancel();
+ adminDataset.cancel();
userAccountSet.cancel();
dataAccountSet.cancel();
contractAccountSet.cancel();
}
- @Override
public boolean isReadonly() {
return readonly;
}
+ void setReadonly() {
+ this.readonly = true;
+ this.adminDataset.setReadonly();
+ this.userAccountSet.setReadonly();
+ this.dataAccountSet.setReadonly();
+ this.contractAccountSet.setReadonly();
+ }
+
}
\ No newline at end of file
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerEditor.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerEditor.java
index 46c21655..466dd30a 100644
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerEditor.java
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerEditor.java
@@ -11,7 +11,7 @@ import com.jd.blockchain.ledger.TransactionRequest;
*
- * 对账本数据({@link #getDataSet()})的批量更改可以作为一个交易({@link LedgerTransaction})整体提交暂存,形成暂存点;
+ * 对账本数据({@link #getDataset()})的批量更改可以作为一个交易({@link LedgerTransaction})整体提交暂存,形成暂存点;
*
*
* @author huanghaiquan
@@ -33,11 +33,25 @@ public interface LedgerEditor {
*/
long getBlockHeight();
+ /**
+ * 最新的账本数据集;
+ *
+ * @return
+ */
+ LedgerDataset getLedgerDataset();
+
+ /**
+ * 最新的交易集合;
+ *
+ * @return
+ */
+ TransactionSet getTransactionSet();
+
/**
* 开始新事务;
*
* 方法返回之前,将会校验交易请求的用户签名列表和节点签名列表,并在后续对数据集
- * {@link LedgerTransactionContext#getDataSet()} 的操作时,校验这些用户和节点是否具备权限;
+ * {@link LedgerTransactionContext#getDataset()} 的操作时,校验这些用户和节点是否具备权限;
*
* 校验失败将引发异常 {@link LedgerException};
*
+ *
+ * 在成功执行 {@link #prepareLedger(KVStorageService, DigitalSignature...)} 之前总是返回
+ * null;
+ *
+ * @return
+ */
+ public HashDigest getLedgerHash() {
+ return genesisBlock == null ? null : genesisBlock.getHash();
+ }
+
+ /**
+ * @param initSetting
+ * @param initTxContent
+ */
+ private LedgerInitializer(LedgerInitSetting initSetting, TransactionContent initTxContent) {
+ this.initSetting = initSetting;
+ this.initTxContent = initTxContent;
+ }
+
+ public TransactionContent getTransactionContent() {
+ return initTxContent;
+ }
+
+ public static LedgerInitializer create(LedgerInitSetting initSetting, SecurityInitSettings securityInitSettings) {
+ // 生成创世交易;
+ TransactionContent initTxContent = buildGenesisTransaction(initSetting, securityInitSettings);
+
+ return new LedgerInitializer(initSetting, initTxContent);
+ }
+
+ /**
+ * 根据初始化配置,生成创始交易;
+ *
+ * (1) 账本初始化 {@link LedgerInitOperation}:此操作仅用于锚定了原始的交易配置,对应的
+ * {@link OperationHandle} 执行空操作,由“创世交易”其余的操作来表达对账本的实际修改;
+ * (2) 注册用户 {@link UserRegisterOperation}:有一项或者多项;
+ * (3) 配置角色 {@link RolesConfigureOperation}:有一项或者多项;
+ * (4) 授权用户 {@link UserAuthorizeOperation}:有一项或者多项;
+ *
+ * @param initSetting
+ * @param securityInitSettings
+ * @return
+ */
+ public static TransactionContent buildGenesisTransaction(LedgerInitSetting initSetting,
+ SecurityInitSettings securityInitSettings) {
+ // 账本初始化交易的账本 hash 为 null;
+ TransactionBuilder initTxBuilder = new TxBuilder(null);
+
+ // 定义账本初始化操作;
+ initTxBuilder.ledgers().create(initSetting);
+
+ // TODO: 注册参与方; 目前由 LedgerInitSetting 定义,在 LedgerAdminDataset 中解释执行;
+
+ // 注册用户;
+ for (ParticipantNode p : initSetting.getConsensusParticipants()) {
+ // TODO:暂时只支持注册用户的初始化操作;
+ BlockchainIdentity superUserId = new BlockchainIdentityData(p.getPubKey());
+ initTxBuilder.users().register(superUserId);
+ }
+
+ // 配置角色;
+ for (RoleInitSettings roleSettings : securityInitSettings.getRoles()) {
+ initTxBuilder.security().roles().configure(roleSettings.getRoleName())
+ .enable(roleSettings.getLedgerPermissions()).enable(roleSettings.getTransactionPermissions());
+ }
+
+ // 授权用户;
+ for (UserAuthInitSettings userAuthSettings : securityInitSettings.getUserAuthorizations()) {
+ initTxBuilder.security().authorziations().forUser(userAuthSettings.getUserAddress())
+ .authorize(userAuthSettings.getRoles())
+ .setPolicy(userAuthSettings.getPolicy());
+ }
+
+ // 账本初始化配置声明的创建时间来初始化交易时间戳;注:不能用本地时间,因为共识节点之间的本地时间系统不一致;
+ return initTxBuilder.prepareContent(initSetting.getCreatedTime());
+ }
+
+ public SignatureDigest signTransaction(PrivKey privKey) {
+ return SignatureUtils.sign(initTxContent, privKey);
+ }
+
+ public DigitalSignature signTransaction(BlockchainKeypair key) {
+ return SignatureUtils.sign(initTxContent, key);
+ }
+
+ /**
+ * 准备创建账本;
+ *
+ * @param storageService 存储服务;
+ * @param nodeSignatures 节点签名列表;
+ * @return
+ */
+ public LedgerBlock prepareLedger(KVStorageService storageService, DigitalSignature... nodeSignatures) {
+ if (genesisBlock != null) {
+ throw new LedgerInitException("The ledger has been prepared!");
+ }
+ // 生成账本;
+ this.ledgerEditor = createLedgerEditor(this.initSetting, storageService);
+ this.genesisBlock = prepareLedger(ledgerEditor, nodeSignatures);
+
+ return genesisBlock;
+ }
+
+ public void commit() {
+ if (committed) {
+ throw new LedgerInitException("The ledger has been committed!");
+ }
+ if (canceled) {
+ throw new LedgerInitException("The ledger has been canceled!");
+ }
+ committed = true;
+ this.txResultsHandle.commit();
+ }
+
+ public void cancel() {
+ if (canceled) {
+ throw new LedgerInitException("The ledger has been canceled!");
+ }
+ if (committed) {
+ throw new LedgerInitException("The ledger has been committed!");
+ }
+ this.ledgerEditor.cancel();
+ }
+
+ public static LedgerEditor createLedgerEditor(LedgerInitSetting initSetting, KVStorageService storageService) {
+ LedgerEditor genesisBlockEditor = LedgerTransactionalEditor.createEditor(initSetting,
+ LedgerManage.LEDGER_PREFIX, storageService.getExPolicyKVStorage(),
+ storageService.getVersioningKVStorage());
+ return genesisBlockEditor;
+ }
+
+ /**
+ * 初始化账本数据,返回创始区块;
+ *
+ * @param ledgerEditor
+ * @return
+ */
+ private LedgerBlock prepareLedger(LedgerEditor ledgerEditor, DigitalSignature... nodeSignatures) {
+ // 初始化时,自动将参与方注册为账本的用户;
+ TxRequestBuilder txReqBuilder = new TxRequestBuilder(this.initTxContent);
+ txReqBuilder.addNodeSignature(nodeSignatures);
+
+ TransactionRequest txRequest = txReqBuilder.buildRequest();
+
+ TransactionBatchProcessor txProcessor = new TransactionBatchProcessor(FULL_PERMISSION_SECURITY_MANAGER,
+ ledgerEditor, EMPTY_LEDGER, DEFAULT_OP_HANDLE_REG);
+
+ txProcessor.schedule(txRequest);
+
+ txResultsHandle = txProcessor.prepare();
+ return txResultsHandle.getBlock();
+ }
+
+ private static class EmptyLedgerQuery implements LedgerQuery{
+
+ private EmptyLedgerDataset dataset;
+
+ @Override
+ public HashDigest getHash() {
+ return null;
+ }
+
+ @Override
+ public long getLatestBlockHeight() {
+ return 0;
+ }
+
+ @Override
+ public HashDigest getLatestBlockHash() {
+ return null;
+ }
+
+ @Override
+ public LedgerBlock getLatestBlock() {
+ return null;
+ }
+
+ @Override
+ public HashDigest getBlockHash(long height) {
+ return null;
+ }
+
+ @Override
+ public LedgerBlock getBlock(long height) {
+ return null;
+ }
+
+ @Override
+ public LedgerAdminInfo getAdminInfo() {
+ return null;
+ }
+
+ @Override
+ public LedgerAdminInfo getAdminInfo(LedgerBlock block) {
+ return null;
+ }
+
+ @Override
+ public LedgerAdminSettings getAdminSettings() {
+ return null;
+ }
+
+ @Override
+ public LedgerAdminSettings getAdminSettings(LedgerBlock block) {
+ return null;
+ }
+
+ @Override
+ public LedgerBlock getBlock(HashDigest hash) {
+ return null;
+ }
+
+ @Override
+ public LedgerDataQuery getLedgerData(LedgerBlock block) {
+ return dataset;
+ }
+
+ @Override
+ public TransactionQuery getTransactionSet(LedgerBlock block) {
+ return null;
+ }
+
+ @Override
+ public UserAccountQuery getUserAccountSet(LedgerBlock block) {
+ return dataset.getUserAccountSet();
+ }
+
+ @Override
+ public DataAccountQuery getDataAccountSet(LedgerBlock block) {
+ return dataset.getDataAccountSet();
+ }
+
+ @Override
+ public ContractAccountQuery getContractAccountSet(LedgerBlock block) {
+ return dataset.getContractAccountset();
+ }
+
+ @Override
+ public LedgerBlock retrieveLatestBlock() {
+ return null;
+ }
+
+ @Override
+ public long retrieveLatestBlockHeight() {
+ return 0;
+ }
+
+ @Override
+ public HashDigest retrieveLatestBlockHash() {
+ return null;
+ }
+
+ }
+
+}
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerManage.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerManage.java
index 0e2ae587..69cafb95 100644
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerManage.java
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerManage.java
@@ -1,7 +1,6 @@
package com.jd.blockchain.ledger.core;
import com.jd.blockchain.crypto.HashDigest;
-import com.jd.blockchain.ledger.LedgerInitSetting;
import com.jd.blockchain.storage.service.KVStorageService;
/**
@@ -12,19 +11,21 @@ import com.jd.blockchain.storage.service.KVStorageService;
*/
public interface LedgerManage extends LedgerService {
- LedgerRepository register(HashDigest ledgerHash, KVStorageService storageService);
+ static final String LEDGER_PREFIX = "LDG://";
+
+ LedgerQuery register(HashDigest ledgerHash, KVStorageService storageService);
void unregister(HashDigest ledgerHash);
- /**
- * 创建新账本;
- *
- * @param initSetting
- * 初始化配置;
- * @param initPermissions
- * 参与者的初始化授权列表;与参与者列表一致;
- * @return
- */
- LedgerEditor newLedger(LedgerInitSetting initSetting, KVStorageService storageService);
+// /**
+// * 创建新账本;
+// *
+// * @param initSetting
+// * 初始化配置;
+// * @param initPermissions
+// * 参与者的初始化授权列表;与参与者列表一致;
+// * @return
+// */
+// LedgerEditor newLedger(LedgerInitSetting initSetting, KVStorageService storageService);
}
\ No newline at end of file
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerManager.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerManager.java
similarity index 80%
rename from source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerManager.java
rename to source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerManager.java
index 19dfee44..715c68f3 100644
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerManager.java
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerManager.java
@@ -1,4 +1,4 @@
-package com.jd.blockchain.ledger.core.impl;
+package com.jd.blockchain.ledger.core;
import java.util.HashMap;
import java.util.Map;
@@ -9,11 +9,6 @@ import com.jd.blockchain.crypto.CryptoProvider;
import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.ledger.CryptoSetting;
import com.jd.blockchain.ledger.LedgerException;
-import com.jd.blockchain.ledger.LedgerInitSetting;
-import com.jd.blockchain.ledger.core.LedgerConsts;
-import com.jd.blockchain.ledger.core.LedgerEditor;
-import com.jd.blockchain.ledger.core.LedgerManage;
-import com.jd.blockchain.ledger.core.LedgerRepository;
import com.jd.blockchain.storage.service.ExPolicyKVStorage;
import com.jd.blockchain.storage.service.KVStorageService;
import com.jd.blockchain.storage.service.VersioningKVStorage;
@@ -27,16 +22,6 @@ import com.jd.blockchain.utils.codec.Base58Utils;
*/
public class LedgerManager implements LedgerManage {
- private static final String LEDGER_PREFIX = "LDG://";
-
- // @Autowired
- // private ExistentialKVStorage exPolicyStorage;
- //
- // @Autowired
- // private VersioningKVStorage versioningStorage;
-
- // private PrivilegeModelSetting privilegeModel = new PrivilegeModelConfig();
-
private Map
*
* @param address
* @param pubKey
- * @param dataRootHash merkle root hash of account's data; if null be set,
- * create a new empty merkle dataset;
+ * @param dataRootHash merkle root hash of account's data; if set to a null value,
+ * an empty merkle dataset is created;
* @param cryptoSetting
* @param exStorage
* @param verStorage
* @param readonly
* @param accessPolicy
*/
- public BaseAccount(Bytes address, PubKey pubKey, HashDigest dataRootHash, CryptoSetting cryptoSetting,
+ public MerkleAccount(Bytes address, PubKey pubKey, HashDigest dataRootHash, CryptoSetting cryptoSetting,
String keyPrefix, ExPolicyKVStorage exStorage, VersioningKVStorage verStorage, boolean readonly) {
this(new BlockchainIdentityData(address, pubKey), dataRootHash, cryptoSetting, keyPrefix, exStorage, verStorage,
readonly);
}
- public BaseAccount(BlockchainIdentity bcid, HashDigest dataRootHash, CryptoSetting cryptoSetting, String keyPrefix,
+ public MerkleAccount(BlockchainIdentity bcid, HashDigest dataRootHash, CryptoSetting cryptoSetting, String keyPrefix,
ExPolicyKVStorage exStorage, VersioningKVStorage verStorage, boolean readonly) {
this.bcid = bcid;
this.dataset = new MerkleDataSet(dataRootHash, cryptoSetting, keyPrefix, exStorage, verStorage, readonly);
@@ -168,7 +169,7 @@ public class BaseAccount implements AccountHeader, MerkleProvable, Transactional
* @param key
* @return
*/
- public long getKeyVersion(Bytes key) {
+ public long getVersion(Bytes key) {
return dataset.getVersion(key);
}
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/AccountSet.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleAccountSet.java
similarity index 80%
rename from source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/AccountSet.java
rename to source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleAccountSet.java
index bb57cd3c..d3e507ba 100644
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/AccountSet.java
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleAccountSet.java
@@ -12,14 +12,17 @@ import com.jd.blockchain.ledger.AccountHeader;
import com.jd.blockchain.ledger.BytesValue;
import com.jd.blockchain.ledger.CryptoSetting;
import com.jd.blockchain.ledger.LedgerException;
+import com.jd.blockchain.ledger.MerkleProof;
+import com.jd.blockchain.ledger.MerkleSnapshot;
import com.jd.blockchain.storage.service.ExPolicyKVStorage;
import com.jd.blockchain.storage.service.VersioningKVStorage;
import com.jd.blockchain.utils.Bytes;
import com.jd.blockchain.utils.Transactional;
-public class AccountSet implements Transactional, MerkleProvable {
+public class MerkleAccountSet implements Transactional, MerkleProvable, AccountQuery
@@ -183,12 +206,9 @@ public class MerkleDataSet implements Transactional, MerkleProvable {
* If updating is performed, the version of the key increase by 1.
* If creating is performed, the version of the key initialize by 0.
*
- * @param key
- * The key of data;
- * @param value
- * The value of data;
- * @param version
- * The expected latest version of the key.
+ * @param key The key of data;
+ * @param value The value of data;
+ * @param version The expected latest version of the key.
* @return The new version of the key.
* If the key is new created success, then return 0;
* If the key is updated success, then return the new version;
@@ -210,12 +230,9 @@ public class MerkleDataSet implements Transactional, MerkleProvable {
* If updating is performed, the version of the key increase by 1.
* If creating is performed, the version of the key initialize by 0.
*
- * @param key
- * The key of data;
- * @param value
- * The value of data;
- * @param version
- * The expected latest version of the key.
+ * @param key The key of data;
+ * @param value The value of data;
+ * @param version The expected latest version of the key.
* @return The new version of the key.
* If the key is new created success, then return 0;
* If the key is updated success, then return the new version;
@@ -404,12 +421,22 @@ public class MerkleDataSet implements Transactional, MerkleProvable {
return getDataEntry(Bytes.fromString(key));
}
+ /**
+ *
+ * @param key
+ * @return Null if the key doesn't exist!
+ */
public VersioningKVEntry getDataEntry(Bytes key) {
long latestVersion = getMerkleVersion(key);
if (latestVersion < 0) {
return null;
}
- return valueStorage.getEntry(key, latestVersion);
+ Bytes dataKey = encodeDataKey(key);
+ byte[] value = valueStorage.get(dataKey, latestVersion);
+ if (value == null) {
+ return null;
+ }
+ return new VersioningKVData(key, latestVersion, value);
}
public VersioningKVEntry getDataEntry(Bytes key, long version) {
@@ -420,7 +447,12 @@ public class MerkleDataSet implements Transactional, MerkleProvable {
return null;
}
version = version < 0 ? latestVersion : version;
- return valueStorage.getEntry(key, version);
+ Bytes dataKey = encodeDataKey(key);
+ byte[] value = valueStorage.get(dataKey, version);
+ if (value == null) {
+ return null;
+ }
+ return new VersioningKVData(key, version, value);
}
public MerkleDataEntry getMerkleEntry(Bytes key, long version) {
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleProvable.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleProvable.java
index 2f93bad7..b41e6856 100644
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleProvable.java
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleProvable.java
@@ -1,11 +1,10 @@
package com.jd.blockchain.ledger.core;
-import com.jd.blockchain.crypto.HashDigest;
+import com.jd.blockchain.ledger.MerkleProof;
+import com.jd.blockchain.ledger.MerkleSnapshot;
import com.jd.blockchain.utils.Bytes;
-public interface MerkleProvable {
-
- HashDigest getRootHash();
+public interface MerkleProvable extends MerkleSnapshot {
/**
* Get the merkle proof of the latest version of specified key;
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleTree.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleTree.java
index 7c3c077c..d86facba 100644
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleTree.java
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleTree.java
@@ -20,6 +20,9 @@ import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.crypto.HashFunction;
import com.jd.blockchain.ledger.CryptoSetting;
import com.jd.blockchain.ledger.LedgerException;
+import com.jd.blockchain.ledger.MerkleDataNode;
+import com.jd.blockchain.ledger.MerkleNode;
+import com.jd.blockchain.ledger.MerkleProof;
import com.jd.blockchain.storage.service.ExPolicyKVStorage;
import com.jd.blockchain.storage.service.ExPolicyKVStorage.ExPolicy;
import com.jd.blockchain.utils.Bytes;
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MultiIDsPolicy.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MultiIDsPolicy.java
new file mode 100644
index 00000000..20f1caab
--- /dev/null
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MultiIDsPolicy.java
@@ -0,0 +1,21 @@
+package com.jd.blockchain.ledger.core;
+
+/**
+ * 多重身份的校验策略;
+ *
+ * @author huanghaiquan
+ *
+ */
+public enum MultiIDsPolicy {
+
+ /**
+ * 至少有一个都能通过;
+ */
+ AT_LEAST_ONE,
+
+ /**
+ * 每一个都能通过;
+ */
+ ALL
+
+}
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/OpeningAccessPolicy.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/OpeningAccessPolicy.java
similarity index 82%
rename from source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/OpeningAccessPolicy.java
rename to source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/OpeningAccessPolicy.java
index 14c5b9b4..6628aad3 100644
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/OpeningAccessPolicy.java
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/OpeningAccessPolicy.java
@@ -1,8 +1,7 @@
-package com.jd.blockchain.ledger.core.impl;
+package com.jd.blockchain.ledger.core;
import com.jd.blockchain.crypto.PubKey;
import com.jd.blockchain.ledger.AccountHeader;
-import com.jd.blockchain.ledger.core.AccountAccessPolicy;
import com.jd.blockchain.utils.Bytes;
/**
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/OperationHandle.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/OperationHandle.java
index e1a0f567..ac3dbbec 100644
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/OperationHandle.java
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/OperationHandle.java
@@ -2,8 +2,6 @@ package com.jd.blockchain.ledger.core;
import com.jd.blockchain.ledger.BytesValue;
import com.jd.blockchain.ledger.Operation;
-import com.jd.blockchain.ledger.core.impl.OperationHandleContext;
-
public interface OperationHandle {
@@ -13,42 +11,22 @@ public interface OperationHandle {
* @param operationType
* @return
*/
- boolean support(Class> operationType);
+ Class> getOperationType();
/**
* 同步解析和执行操作;
*
*
- * @param op
- * 操作实例;
- * @param newBlockDataset
- * 需要修改的新区块的数据集;
- * @param requestContext
- * 交易请求上下文;
- * @param previousBlockDataset
- * 新区块的前一个区块的数据集;即未提交新区块之前的经过共识的账本最新数据集;
+ * @param op 操作实例;
+ * @param newBlockDataset 需要修改的新区块的数据集;
+ * @param requestContext 交易请求上下文;
+ * @param previousBlockDataset 新区块的前一个区块的数据集;即未提交新区块之前的经过共识的账本最新数据集;注:此数据集是只读的;
*
- * @return 操作执行结果
+ * @param handleContext 操作上下文;`
+ * @param ledgerService
+ * @return
*/
- BytesValue process(Operation op, LedgerDataSet newBlockDataset, TransactionRequestContext requestContext,
- LedgerDataSet previousBlockDataset, OperationHandleContext handleContext, LedgerService ledgerService);
+ BytesValue process(Operation op, LedgerDataset newBlockDataset, TransactionRequestExtension requestContext,
+ LedgerQuery ledger, OperationHandleContext handleContext);
-// /**
-// * 异步解析和执行操作;
-// * TODO 未来规划实现
-// *
-// *
-// * @param op
-// * 操作实例;
-// * @param newBlockDataset
-// * 需要修改的新区块的数据集;
-// * @param requestContext
-// * 交易请求上下文;
-// * @param previousBlockDataset
-// * 新区块的前一个区块的数据集;即未提交新区块之前的经过共识的账本最新数据集;
-// *
-// * @return 操作执行结果
-// */
-// AsyncFuture
+ *
+ * @param participant
+ */
+ public void updateConsensusParticipant(ParticipantNode participant) {
+ Bytes key = encodeKey(participant.getAddress());
+ byte[] participantBytes = BinaryProtocol.encode(participant, ParticipantNode.class);
+ long version = dataset.getVersion(key);
+ if (version < 0) {
+ throw new LedgerException("Participant not exist, update failed!");
+ }
+
+ long nv = dataset.setValue(key, participantBytes, version);
+ if (nv < 0) {
+ throw new LedgerException("Participant update failed!");
+ }
+ }
+
+ private Bytes encodeKey(Bytes address) {
+ return address;
+ }
+
+ @Override
+ public boolean contains(Bytes address) {
+ Bytes key = encodeKey(address);
+ long latestVersion = dataset.getVersion(key);
+ return latestVersion > -1;
}
/**
@@ -87,7 +115,8 @@ public class ParticipantDataSet implements Transactional, MerkleProvable {
* @param address
* @return
*/
- public ParticipantNode getParticipant(String address) {
+ @Override
+ public ParticipantNode getParticipant(Bytes address) {
Bytes key = encodeKey(address);
byte[] bytes = dataset.getValue(key);
if (bytes == null) {
@@ -95,11 +124,12 @@ public class ParticipantDataSet implements Transactional, MerkleProvable {
}
return BinaryProtocol.decode(bytes);
}
-
+
+ @Override
public ParticipantNode[] getParticipants() {
- byte[][] bytes = dataset.getLatestValues(0, (int)dataset.getDataCount());
+ byte[][] bytes = dataset.getLatestValues(0, (int) dataset.getDataCount());
ParticipantNode[] pns = new ParticipantNode[bytes.length];
-
+
for (int i = 0; i < pns.length; i++) {
pns[i] = BinaryProtocol.decode(bytes[i]);
}
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/PermissionService.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/PermissionService.java
index b3b9a7c2..78be086b 100644
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/PermissionService.java
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/PermissionService.java
@@ -1,7 +1,5 @@
package com.jd.blockchain.ledger.core;
-import java.util.SortedSet;
-
public interface PermissionService {
boolean checkLedgerPermission();
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/PrivilegeDataSet.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/PrivilegeDataSet.java
deleted file mode 100644
index 9bdc3f3b..00000000
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/PrivilegeDataSet.java
+++ /dev/null
@@ -1,21 +0,0 @@
-//package com.jd.blockchain.ledger.core;
-//
-//import com.jd.blockchain.crypto.hash.HashDigest;
-//import com.jd.blockchain.ledger.data.DigitalSignatureBlob;
-//
-//import my.utils.io.ExistentialKVStorage;
-//import my.utils.io.VersioningKVStorage;
-//
-//public class PrivilegeDataSet extends GenericMerkleDataSet
+ * 如果版本校验不匹配,则返回 -1;
+ *
+ * @param roleAuth
+ * @return
+ */
+ private long setRolePrivilege(RolePrivileges roleAuth) {
+ if (roleAuth.getRoleName().length() > MAX_ROLE_NAME_LENGTH) {
+ throw new LedgerException("Too long role name!");
+ }
+ Bytes key = encodeKey(roleAuth.getRoleName());
+ byte[] privilegeBytes = BinaryProtocol.encode(roleAuth, PrivilegeSet.class);
+ return dataset.setValue(key, privilegeBytes, roleAuth.getVersion());
+ }
+
+ /**
+ * 更新角色权限;
+ * 如果指定的角色不存在,或者版本不匹配,则引发 {@link LedgerException} 异常;
+ *
+ * @param participant
+ */
+ @Override
+ public void updateRolePrivilege(RolePrivileges roleAuth) {
+ long nv = setRolePrivilege(roleAuth);
+ if (nv < 0) {
+ throw new LedgerException("Update to RoleAuthorization[" + roleAuth.getRoleName()
+ + "] failed due to wrong version[" + roleAuth.getVersion() + "] !");
+ }
+ }
+
+ /**
+ * 授权角色指定的权限;
+ * 如果角色不存在,则返回 -1;
+ *
+ * @param roleName 角色;
+ * @param permissions 权限列表;
+ * @return
+ */
+ @Override
+ public long enablePermissions(String roleName, LedgerPermission... permissions) {
+ RolePrivileges roleAuth = getRolePrivilege(roleName);
+ if (roleAuth == null) {
+ return -1;
+ }
+ roleAuth.getLedgerPrivilege().enable(permissions);
+ return setRolePrivilege(roleAuth);
+ }
+
+ /**
+ * 授权角色指定的权限;
+ * 如果角色不存在,则返回 -1;
+ *
+ * @param roleName 角色;
+ * @param permissions 权限列表;
+ * @return
+ */
+ @Override
+ public long enablePermissions(String roleName, TransactionPermission... permissions) {
+ RolePrivileges roleAuth = getRolePrivilege(roleName);
+ if (roleAuth == null) {
+ return -1;
+ }
+ roleAuth.getTransactionPrivilege().enable(permissions);
+ return setRolePrivilege(roleAuth);
+ }
+
+ /**
+ * 禁止角色指定的权限;
+ * 如果角色不存在,则返回 -1;
+ *
+ * @param roleName 角色;
+ * @param permissions 权限列表;
+ * @return
+ */
+ @Override
+ public long disablePermissions(String roleName, LedgerPermission... permissions) {
+ RolePrivileges roleAuth = getRolePrivilege(roleName);
+ if (roleAuth == null) {
+ return -1;
+ }
+ roleAuth.getLedgerPrivilege().disable(permissions);
+ return setRolePrivilege(roleAuth);
+ }
+
+ /**
+ * 禁止角色指定的权限;
+ * 如果角色不存在,则返回 -1;
+ *
+ * @param roleName 角色;
+ * @param permissions 权限列表;
+ * @return
+ */
+ @Override
+ public long disablePermissions(String roleName, TransactionPermission... permissions) {
+ RolePrivileges roleAuth = getRolePrivilege(roleName);
+ if (roleAuth == null) {
+ return -1;
+ }
+ roleAuth.getTransactionPrivilege().disable(permissions);
+ return setRolePrivilege(roleAuth);
+ }
+
+ /**
+ * 授权角色指定的权限;
+ * 如果角色不存在,则返回 -1;
+ *
+ * @param roleName
+ * @param ledgerPermissions
+ * @param txPermissions
+ * @return
+ */
+ @Override
+ public long enablePermissions(String roleName, LedgerPermission[] ledgerPermissions,
+ TransactionPermission[] txPermissions) {
+ RolePrivileges roleAuth = getRolePrivilege(roleName);
+ if (roleAuth == null) {
+ return -1;
+ }
+ roleAuth.getLedgerPrivilege().enable(ledgerPermissions);
+ roleAuth.getTransactionPrivilege().enable(txPermissions);
+ return setRolePrivilege(roleAuth);
+ }
+
+ /**
+ * 禁用角色指定的权限;
+ * 如果角色不存在,则返回 -1;
+ *
+ * @param roleName
+ * @param ledgerPermissions
+ * @param txPermissions
+ * @return
+ */
+ @Override
+ public long disablePermissions(String roleName, LedgerPermission[] ledgerPermissions,
+ TransactionPermission[] txPermissions) {
+ RolePrivileges roleAuth = getRolePrivilege(roleName);
+ if (roleAuth == null) {
+ return -1;
+ }
+ roleAuth.getLedgerPrivilege().disable(ledgerPermissions);
+ roleAuth.getTransactionPrivilege().disable(txPermissions);
+ return setRolePrivilege(roleAuth);
+ }
+
+ private Bytes encodeKey(String address) {
+ // return id + "";
+ return Bytes.fromString(address);
+ }
+
+ /**
+ * 查询角色权限;
+ *
+ *
+ * 如果不存在,则返回 null;
+ *
+ * @param address
+ * @return
+ */
+ @Override
+ public RolePrivileges getRolePrivilege(String roleName) {
+ // 只返回最新版本;
+ Bytes key = encodeKey(roleName);
+ VersioningKVEntry kv = dataset.getDataEntry(key);
+ if (kv == null) {
+ return null;
+ }
+ PrivilegeSet privilege = BinaryProtocol.decode(kv.getValue());
+ return new RolePrivileges(roleName, kv.getVersion(), privilege);
+ }
+
+ @Override
+ public RolePrivileges[] getRolePrivileges(int index, int count) {
+ VersioningKVEntry[] kvEntries = dataset.getLatestDataEntries(index, count);
+ RolePrivileges[] pns = new RolePrivileges[kvEntries.length];
+ PrivilegeSet privilege;
+ for (int i = 0; i < pns.length; i++) {
+ privilege = BinaryProtocol.decode(kvEntries[i].getValue());
+ pns[i] = new RolePrivileges(kvEntries[i].getKey().toUTF8String(), kvEntries[i].getVersion(), privilege);
+ }
+ return pns;
+ }
+
+ @Override
+ public RolePrivileges[] getRolePrivileges() {
+ return getRolePrivileges(0, (int) getRoleCount());
+ }
+
+ @Override
+ public boolean isReadonly() {
+ return dataset.isReadonly();
+ }
+
+ @Override
+ public boolean contains(String roleName) {
+ Bytes key = encodeKey(roleName);
+ return dataset.getVersion(key) > -1;
+ }
+}
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/SecurityContext.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/SecurityContext.java
new file mode 100644
index 00000000..d3ad83ba
--- /dev/null
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/SecurityContext.java
@@ -0,0 +1,38 @@
+package com.jd.blockchain.ledger.core;
+
+import java.util.Set;
+
+import com.jd.blockchain.ledger.BlockchainIdentity;
+import com.jd.blockchain.ledger.LedgerPermission;
+import com.jd.blockchain.ledger.LedgerSecurityException;
+import com.jd.blockchain.ledger.TransactionPermission;
+
+public class SecurityContext {
+
+ private static ThreadLocal
+ *
+ * @param permission 要检查的权限;
+ * @param midPolicy 针对多个签名用户的权限策略;
+ * @return 返回 true 表示获得授权; 返回 false 表示未获得授权;
+ */
+ boolean isEndpointEnable(LedgerPermission permission, MultiIDsPolicy midPolicy);
+
+ /**
+ * 检查签署交易的终端用户(来自{@link TransactionRequest#getEndpointSignatures()})是否被授权了参数指定的权限;
+ *
+ * @param permission 要检查的权限;
+ * @param midPolicy 针对多个签名用户的权限策略;
+ * @return 返回 true 表示获得授权; 返回 false 表示未获得授权;
+ */
+ boolean isEndpointEnable(TransactionPermission permission, MultiIDsPolicy midPolicy);
+
+ /**
+ * 检查签署交易的节点参与方(来自{@link TransactionRequest#getNodeSignatures()})是否被授权了参数指定的权限;
+ *
+ * @param permission 要检查的权限;
+ * @param midPolicy 针对多个签名用户的权限策略;
+ * @return 返回 true 表示获得授权; 返回 false 表示未获得授权;
+ */
+ boolean isNodeEnable(LedgerPermission permission, MultiIDsPolicy midPolicy);
+
+ /**
+ * 检查签署交易的节点参与方(来自{@link TransactionRequest#getNodeSignatures()})是否被授权了参数指定的权限;
+ *
+ * @param permission 要检查的权限;
+ * @param midPolicy 针对多个签名用户的权限策略;
+ * @return 返回 true 表示获得授权; 返回 false 表示未获得授权;
+ */
+ boolean isNodeEnable(TransactionPermission permission, MultiIDsPolicy midPolicy);
+
+ /**
+ * 检查终端身份的合法性;
+ *
+ * @param midPolicy
+ * @throws LedgerSecurityException
+ */
+ void checkEndpointValidity(MultiIDsPolicy midPolicy) throws LedgerSecurityException;
+
+ /**
+ * 检查节点身份的合法性;
+ *
+ * @param midPolicy
+ * @throws LedgerSecurityException
+ */
+ void checkNodeValidity(MultiIDsPolicy midPolicy) throws LedgerSecurityException;
+
+ /**
+ * 检查签署交易的终端用户(来自{@link TransactionRequest#getEndpointSignatures()})是否被授权了参数指定的权限;
+ * 如果未获授权,方法将引发 {@link LedgerSecurityException} 异常;
+ *
+ * @param permission 要检查的权限;
+ * @param midPolicy 针对多个签名用户的权限策略;
+ * @throws LedgerSecurityException
+ */
+ void checkEndpointPermission(LedgerPermission permission, MultiIDsPolicy midPolicy) throws LedgerSecurityException;
+
+ /**
+ * 检查签署交易的终端用户(来自{@link TransactionRequest#getEndpointSignatures()})是否被授权了参数指定的权限;
+ * 如果未获授权,方法将引发 {@link LedgerSecurityException} 异常;
+ *
+ * @param permission
+ * @param midPolicy
+ * @throws LedgerSecurityException
+ */
+ void checkEndpointPermission(TransactionPermission permission, MultiIDsPolicy midPolicy)
+ throws LedgerSecurityException;
+
+ /**
+ * 检查签署交易的节点参与方(来自{@link TransactionRequest#getNodeSignatures()})是否被授权了参数指定的权限;
+ * 如果未获授权,方法将引发 {@link LedgerSecurityException} 异常;
+ *
+ * @param permission
+ * @param midPolicy
+ * @throws LedgerSecurityException
+ */
+ void checkNodePermission(LedgerPermission permission, MultiIDsPolicy midPolicy) throws LedgerSecurityException;
+
+ /**
+ * 检查签署交易的节点参与方(来自{@link TransactionRequest#getNodeSignatures()})是否被授权了参数指定的权限;
+ * 如果未获授权,方法将引发 {@link LedgerSecurityException} 异常;
+ *
+ * @param permission
+ * @param midPolicy
+ * @throws LedgerSecurityException
+ */
+ void checkNodePermission(TransactionPermission permission, MultiIDsPolicy midPolicy) throws LedgerSecurityException;
+
+}
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/SettingContext.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/SettingContext.java
index 516b2acf..f464db7f 100644
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/SettingContext.java
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/SettingContext.java
@@ -1,51 +1,51 @@
-package com.jd.blockchain.ledger.core;
-
-public class SettingContext {
-
- private static final TxSettingContext txSettings = new TxSettingContext();
-
- private static final QueryingSettingContext queryingSettings = new QueryingSettingContext();
-
- public static TxSettingContext txSettings() {
- return txSettings;
- }
-
- public static QueryingSettingContext queryingSettings() {
- return queryingSettings;
- }
-
- /**
- * 与交易处理相关的设置;
- * @author huanghaiquan
- *
- */
- public static class TxSettingContext {
-
- public boolean verifyLedger() {
- return true;
- }
-
- public boolean verifySignature() {
- return true;
- }
-
- }
-
- /**
- * 与账本查询相关的设置;
- * @author huanghaiquan
- *
- */
- public static class QueryingSettingContext {
-
- /**
- * 查询区块等具有 hash 标识符的对象时是否重新校验哈希;
- * @return
- */
- public boolean verifyHash() {
- return false;
- }
-
- }
-
-}
+//package com.jd.blockchain.ledger.core;
+//
+//public class SettingContext {
+//
+// private static final TxSettingContext txSettings = new TxSettingContext();
+//
+// private static final QueryingSettingContext queryingSettings = new QueryingSettingContext();
+//
+// public static TxSettingContext txSettings() {
+// return txSettings;
+// }
+//
+// public static QueryingSettingContext queryingSettings() {
+// return queryingSettings;
+// }
+//
+// /**
+// * 与交易处理相关的设置;
+// * @author huanghaiquan
+// *
+// */
+// public static class TxSettingContext {
+//
+// public boolean verifyLedger() {
+// return true;
+// }
+//
+// public boolean verifySignature() {
+// return true;
+// }
+//
+// }
+//
+// /**
+// * 与账本查询相关的设置;
+// * @author huanghaiquan
+// *
+// */
+// public static class QueryingSettingContext {
+//
+// /**
+// * 查询区块等具有 hash 标识符的对象时是否重新校验哈希;
+// * @return
+// */
+// public boolean verifyHash() {
+// return false;
+// }
+//
+// }
+//
+//}
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/TransactionBatchProcessor.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/TransactionBatchProcessor.java
similarity index 57%
rename from source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/TransactionBatchProcessor.java
rename to source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/TransactionBatchProcessor.java
index aa8fcf93..ae62cdf7 100644
--- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/TransactionBatchProcessor.java
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/TransactionBatchProcessor.java
@@ -1,6 +1,7 @@
-package com.jd.blockchain.ledger.core.impl;
+package com.jd.blockchain.ledger.core;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.Iterator;
import java.util.List;
@@ -15,37 +16,37 @@ import com.jd.blockchain.ledger.DataAccountDoesNotExistException;
import com.jd.blockchain.ledger.IllegalTransactionException;
import com.jd.blockchain.ledger.LedgerBlock;
import com.jd.blockchain.ledger.LedgerException;
+import com.jd.blockchain.ledger.LedgerPermission;
+import com.jd.blockchain.ledger.LedgerSecurityException;
import com.jd.blockchain.ledger.Operation;
import com.jd.blockchain.ledger.OperationResult;
import com.jd.blockchain.ledger.OperationResultData;
+import com.jd.blockchain.ledger.ParticipantDoesNotExistException;
+import com.jd.blockchain.ledger.TransactionContent;
import com.jd.blockchain.ledger.TransactionRequest;
import com.jd.blockchain.ledger.TransactionResponse;
import com.jd.blockchain.ledger.TransactionRollbackException;
import com.jd.blockchain.ledger.TransactionState;
import com.jd.blockchain.ledger.UserDoesNotExistException;
-import com.jd.blockchain.ledger.core.LedgerDataSet;
-import com.jd.blockchain.ledger.core.LedgerEditor;
-import com.jd.blockchain.ledger.core.LedgerService;
-import com.jd.blockchain.ledger.core.LedgerTransactionContext;
-import com.jd.blockchain.ledger.core.OperationHandle;
-import com.jd.blockchain.ledger.core.TransactionRequestContext;
+import com.jd.blockchain.ledger.core.TransactionRequestExtension.Credential;
import com.jd.blockchain.service.TransactionBatchProcess;
import com.jd.blockchain.service.TransactionBatchResult;
import com.jd.blockchain.service.TransactionBatchResultHandle;
+import com.jd.blockchain.transaction.SignatureUtils;
+import com.jd.blockchain.transaction.TxBuilder;
import com.jd.blockchain.transaction.TxResponseMessage;
-import com.jd.blockchain.utils.Bytes;
public class TransactionBatchProcessor implements TransactionBatchProcess {
private static final Logger LOGGER = LoggerFactory.getLogger(TransactionBatchProcessor.class);
- private LedgerService ledgerService;
+ private LedgerSecurityManager securityManager;
private LedgerEditor newBlockEditor;
- private LedgerDataSet previousBlockDataset;
+ private LedgerQuery ledger;
- private OperationHandleRegisteration opHandles;
+ private OperationHandleRegisteration handlesRegisteration;
// 新创建的交易;
private LedgerBlock block;
@@ -56,17 +57,53 @@ public class TransactionBatchProcessor implements TransactionBatchProcess {
private TransactionBatchResult batchResult;
+ public HashDigest getLedgerHash() {
+ return ledger.getHash();
+ }
+
/**
- * @param newBlockEditor 新区块的数据编辑器;
- * @param previousBlockDataset 新区块的前一个区块的数据集;即未提交新区块之前的经过共识的账本最新数据集;
- * @param opHandles 操作处理对象注册表;
+ * @param newBlockEditor 新区块的数据编辑器;
+ * @param ledgerQueryer 账本查询器,只包含新区块的前一个区块的数据集;即未提交新区块之前的经过共识的账本最新数据集;
+ * @param opHandles 操作处理对象注册表;
*/
- public TransactionBatchProcessor(LedgerEditor newBlockEditor, LedgerDataSet previousBlockDataset,
- OperationHandleRegisteration opHandles, LedgerService ledgerService) {
+ public TransactionBatchProcessor(LedgerSecurityManager securityManager, LedgerEditor newBlockEditor,
+ LedgerQuery ledger, OperationHandleRegisteration opHandles) {
+ this.securityManager = securityManager;
this.newBlockEditor = newBlockEditor;
- this.previousBlockDataset = previousBlockDataset;
- this.opHandles = opHandles;
- this.ledgerService = ledgerService;
+ this.ledger = ledger;
+ this.handlesRegisteration = opHandles;
+ }
+
+ public TransactionBatchProcessor(LedgerRepository ledgerRepo, OperationHandleRegisteration handlesRegisteration) {
+ this.ledger = ledgerRepo;
+ this.handlesRegisteration = handlesRegisteration;
+
+ LedgerBlock ledgerBlock = ledgerRepo.getLatestBlock();
+ LedgerDataQuery ledgerDataQuery = ledgerRepo.getLedgerData(ledgerBlock);
+ LedgerAdminDataQuery previousAdminDataset = ledgerDataQuery.getAdminDataset();
+ this.securityManager = new LedgerSecurityManagerImpl(previousAdminDataset.getAdminInfo().getRolePrivileges(),
+ previousAdminDataset.getAdminInfo().getAuthorizations(), previousAdminDataset.getParticipantDataset(),
+ ledgerDataQuery.getUserAccountSet());
+
+ this.newBlockEditor = ledgerRepo.createNextBlock();
+
+ }
+
+ public static TransactionBatchProcess create(LedgerRepository ledgerRepo,
+ OperationHandleRegisteration handlesRegisteration) {
+ LedgerBlock ledgerBlock = ledgerRepo.getLatestBlock();
+ LedgerEditor newBlockEditor = ledgerRepo.createNextBlock();
+ LedgerDataQuery previousBlockDataset = ledgerRepo.getLedgerData(ledgerBlock);
+
+ LedgerAdminDataQuery previousAdminDataset = previousBlockDataset.getAdminDataset();
+ LedgerSecurityManager securityManager = new LedgerSecurityManagerImpl(
+ previousAdminDataset.getAdminInfo().getRolePrivileges(),
+ previousAdminDataset.getAdminInfo().getAuthorizations(), previousAdminDataset.getParticipantDataset(),
+ previousBlockDataset.getUserAccountSet());
+
+ TransactionBatchProcessor processor = new TransactionBatchProcessor(securityManager, newBlockEditor, ledgerRepo,
+ handlesRegisteration);
+ return processor;
}
/*
@@ -82,12 +119,26 @@ public class TransactionBatchProcessor implements TransactionBatchProcess {
try {
LOGGER.debug("Start handling transaction... --[BlockHeight={}][RequestHash={}][TxHash={}]",
newBlockEditor.getBlockHeight(), request.getHash(), request.getTransactionContent().getHash());
+
+ TransactionRequestExtension reqExt = new TransactionRequestExtensionImpl(request);
+
+ // 初始化交易的用户安全策略;
+ SecurityPolicy securityPolicy = securityManager.createSecurityPolicy(reqExt.getEndpointAddresses(),
+ reqExt.getNodeAddresses());
+ SecurityContext.setContextUsersPolicy(securityPolicy);
+
+ // 安全校验;
+ checkSecurity(securityPolicy);
+
+ // 验证交易请求;
+ checkRequest(reqExt);
+
// 创建交易上下文;
// 此调用将会验证交易签名,验签失败将会抛出异常,同时,不记录签名错误的交易到链上;
LedgerTransactionContext txCtx = newBlockEditor.newTransaction(request);
// 处理交易;
- resp = handleTx(request, txCtx);
+ resp = handleTx(reqExt, txCtx);
LOGGER.debug("Complete handling transaction. --[BlockHeight={}][RequestHash={}][TxHash={}]",
newBlockEditor.getBlockHeight(), request.getHash(), request.getTransactionContent().getHash());
@@ -99,10 +150,9 @@ public class TransactionBatchProcessor implements TransactionBatchProcess {
"Ignore transaction caused by IllegalTransactionException! --[BlockHeight=%s][RequestHash=%s][TxHash=%s] --%s",
newBlockEditor.getBlockHeight(), request.getHash(), request.getTransactionContent().getHash(),
e.getMessage()), e);
-
+
} catch (BlockRollbackException e) {
- // 抛弃发生处理异常的交易请求;
-// resp = discard(request, TransactionState.IGNORED_BY_BLOCK_FULL_ROLLBACK);
+ // 发生区块级别的处理异常,向上重新抛出异常进行处理,整个区块可能被丢弃;
LOGGER.error(String.format(
"Ignore transaction caused by BlockRollbackException! --[BlockHeight=%s][RequestHash=%s][TxHash=%s] --%s",
newBlockEditor.getBlockHeight(), request.getHash(), request.getTransactionContent().getHash(),
@@ -116,12 +166,79 @@ public class TransactionBatchProcessor implements TransactionBatchProcess {
newBlockEditor.getBlockHeight(), request.getHash(), request.getTransactionContent().getHash(),
e.getMessage()), e);
+ } finally {
+ // 清空交易的用户安全策略;
+ SecurityContext.removeContextUsersPolicy();
}
responseList.add(resp);
return resp;
}
+ /**
+ * 执行安全验证;
+ */
+ private void checkSecurity(SecurityPolicy securityPolicy) {
+ // 验证节点和终端身份的合法性;
+ // 多重身份签署的必须全部身份都合法;
+ securityPolicy.checkEndpointValidity(MultiIDsPolicy.ALL);
+ securityPolicy.checkNodeValidity(MultiIDsPolicy.ALL);
+
+ // 验证参与方节点是否具有核准交易的权限;
+ securityPolicy.checkNodePermission(LedgerPermission.APPROVE_TX, MultiIDsPolicy.AT_LEAST_ONE);
+ }
+
+ private void checkRequest(TransactionRequestExtension reqExt) {
+ // TODO: 把验签和创建交易并行化;
+ checkTxContentHash(reqExt);
+ checkEndpointSignatures(reqExt);
+ checkNodeSignatures(reqExt);
+ }
+
+ private void checkTxContentHash(TransactionRequestExtension requestExt) {
+ TransactionContent txContent = requestExt.getTransactionContent();
+ if (!TxBuilder.verifyTxContentHash(txContent, txContent.getHash())) {
+ // 由于哈希校验失败,引发IllegalTransactionException,使外部调用抛弃此交易请求;
+ throw new IllegalTransactionException(
+ "Wrong transaction content hash! --[TxHash=" + requestExt.getTransactionContent().getHash() + "]!",
+ TransactionState.IGNORED_BY_WRONG_CONTENT_SIGNATURE);
+ }
+ }
+
+ private void checkNodeSignatures(TransactionRequestExtension request) {
+ TransactionContent txContent = request.getTransactionContent();
+ Collection
*
@@ -131,23 +248,11 @@ public class TransactionBatchProcessor implements TransactionBatchProcess {
* @param txCtx
* @return
*/
- private TransactionResponse handleTx(TransactionRequest request, LedgerTransactionContext txCtx) {
+ private TransactionResponse handleTx(TransactionRequestExtension request, LedgerTransactionContext txCtx) {
TransactionState result;
List
+ *
+ * 如果该用户的授权已经存在,则引发 {@link LedgerException} 异常;
+ *
+ * @param userAddress
+ * @param rolesPolicy
+ * @param roles
+ */
+ @Override
+ public void addUserRoles(Bytes userAddress, RolesPolicy rolesPolicy, String... roles) {
+ UserRoles roleAuth = new UserRoles(userAddress, -1, rolesPolicy);
+ roleAuth.addRoles(roles);
+ long nv = setUserRolesAuthorization(roleAuth);
+ if (nv < 0) {
+ throw new AuthorizationException("Roles authorization of User[" + userAddress + "] already exists!");
+ }
+ }
+
+ /**
+ * 加入新的用户角色授权;
+ *
+ * 如果该用户的授权已经存在,则引发 {@link LedgerException} 异常;
+ *
+ * @param userAddress
+ * @param rolesPolicy
+ * @param roles
+ */
+ @Override
+ public void addUserRoles(Bytes userAddress, RolesPolicy rolesPolicy, Collection
+ * 如果版本校验不匹配,则返回 -1;
+ *
+ * @param userRoles
+ * @return
+ */
+ private long setUserRolesAuthorization(UserRoles userRoles) {
+ if (userRoles.getRoleCount() > MAX_ROLES_PER_USER) {
+ throw new AuthorizationException("The number of roles exceeds the maximum range!");
+ }
+ byte[] rolesetBytes = BinaryProtocol.encode(userRoles, RoleSet.class);
+ return dataset.setValue(userRoles.getUserAddress(), rolesetBytes, userRoles.getVersion());
+ }
+
+ /**
+ * 更新用户角色授权;
+ * 如果指定用户的授权不存在,或者版本不匹配,则引发 {@link LedgerException} 异常;
+ *
+ * @param userRoles
+ */
+ @Override
+ public void updateUserRoles(UserRoles userRoles) {
+ long nv = setUserRolesAuthorization(userRoles);
+ if (nv < 0) {
+ throw new AuthorizationException("Update to roles of user[" + userRoles.getUserAddress()
+ + "] failed due to wrong version[" + userRoles.getVersion() + "] !");
+ }
+ }
+
+ /**
+ * 设置用户的角色;
+ * 如果用户的角色授权不存在,则创建新的授权;
+ *
+ * @param userAddress 用户;
+ * @param policy 角色策略;
+ * @param roles 角色列表;
+ * @return
+ */
+ @Override
+ public long setRoles(Bytes userAddress, RolesPolicy policy, String... roles) {
+ UserRoles userRoles = getUserRoles(userAddress);
+ if (userRoles == null) {
+ userRoles = new UserRoles(userAddress, -1, policy);
+ }
+ userRoles.setPolicy(policy);
+ userRoles.setRoles(roles);
+ return setUserRolesAuthorization(userRoles);
+ }
+
+ /**
+ * 查询角色授权;
+ *
+ *
+ * 如果不存在,则返回 null;
+ *
+ * @param address
+ * @return
+ */
+ @Override
+ public UserRoles getUserRoles(Bytes userAddress) {
+ // 只返回最新版本;
+ VersioningKVEntry kv = dataset.getDataEntry(userAddress);
+ if (kv == null) {
+ return null;
+ }
+ RoleSet roleSet = BinaryProtocol.decode(kv.getValue());
+ return new UserRoles(userAddress, kv.getVersion(), roleSet);
+ }
+
+ @Override
+ public UserRoles[] getUserRoles() {
+ VersioningKVEntry[] kvEntries = dataset.getLatestDataEntries(0, (int) dataset.getDataCount());
+ UserRoles[] pns = new UserRoles[kvEntries.length];
+ RoleSet roleset;
+ for (int i = 0; i < pns.length; i++) {
+ roleset = BinaryProtocol.decode(kvEntries[i].getValue());
+ pns[i] = new UserRoles(kvEntries[i].getKey(), kvEntries[i].getVersion(), roleset);
+ }
+ return pns;
+ }
+
+ @Override
+ public boolean isReadonly() {
+ return dataset.isReadonly();
+ }
+
+}
diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/UserRolesPrivileges.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/UserRolesPrivileges.java
new file mode 100644
index 00000000..dee7fb48
--- /dev/null
+++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/UserRolesPrivileges.java
@@ -0,0 +1,63 @@
+package com.jd.blockchain.ledger.core;
+
+import java.util.Collection;
+
+import com.jd.blockchain.ledger.LedgerPermission;
+import com.jd.blockchain.ledger.LedgerPrivilege;
+import com.jd.blockchain.ledger.PrivilegeBitset;
+import com.jd.blockchain.ledger.RolePrivileges;
+import com.jd.blockchain.ledger.RolesPolicy;
+import com.jd.blockchain.ledger.TransactionPermission;
+import com.jd.blockchain.ledger.TransactionPrivilege;
+import com.jd.blockchain.utils.Bytes;
+
+/**
+ * {@link UserRolesPrivileges} 表示多角色用户的综合权限;
+ *
+ * @author huanghaiquan
+ *
+ */
+class UserRolesPrivileges {
+
+ private Bytes userAddress;
+
+ private LedgerPrivilege ledgerPrivileges;
+
+ private TransactionPrivilege transactionPrivileges;
+
+ public UserRolesPrivileges(Bytes userAddress, RolesPolicy policy, Collection
+ * 期待正确的表现是引发异常而回滚当前交易;
+ */
+ @Test
+ public void testRollbackWhileVersionConfliction() {
+ // 初始化账本到指定的存储库;
+ HashDigest ledgerHash = initLedger(storage, parti0, parti1, parti2, parti3);
+
+ // 重新加载账本;
+ LedgerManager ledgerManager = new LedgerManager();
+ LedgerRepository ledgerRepo = ledgerManager.register(ledgerHash, storage);
+
+ // 创建合约处理器;
+ ContractInvokingHandle contractInvokingHandle = new ContractInvokingHandle();
+
+ // 创建和加载合约实例;
+ BlockchainKeypair contractKey = BlockchainKeyGenerator.getInstance().generate();
+ Bytes contractAddress = contractKey.getAddress();
+ TxTestContractImpl contractInstance = new TxTestContractImpl();
+ contractInvokingHandle.setup(contractAddress, TxTestContract.class, contractInstance);
+
+ // 注册合约处理器;
+ DefaultOperationHandleRegisteration opReg = new DefaultOperationHandleRegisteration();
+ opReg.registerHandle(contractInvokingHandle);
+
+ // 发布指定地址合约
+ deploy(ledgerRepo, ledgerManager, opReg, ledgerHash, contractKey);
+
+ // 注册数据账户;
+ BlockchainKeypair kpDataAccount = BlockchainKeyGenerator.getInstance().generate();
+ contractInstance.setDataAddress(kpDataAccount.getAddress());
+ registerDataAccount(ledgerRepo, ledgerManager, opReg, ledgerHash, kpDataAccount);
+
+ // 调用合约
+ // 构建基于接口调用合约的交易请求,用于测试合约调用;
+ buildBlock(ledgerRepo, ledgerManager, opReg, new TxDefinitor() {
+ @Override
+ public void buildTx(TxBuilder txBuilder) {
+ TxTestContract contractProxy = txBuilder.contract(contractAddress, TxTestContract.class);
+ contractProxy.testRollbackWhileVersionConfliction(kpDataAccount.getAddress().toBase58(), "K1", "V1-0",
+ -1);
+ contractProxy.testRollbackWhileVersionConfliction(kpDataAccount.getAddress().toBase58(), "K2", "V2-0",
+ -1);
+ }
+ });
+ // 预期数据都能够正常写入;
+ KVDataEntry kv1 = ledgerRepo.getDataAccountSet().getAccount(kpDataAccount.getAddress()).getDataEntry("K1",
+ 0);
+ KVDataEntry kv2 = ledgerRepo.getDataAccountSet().getAccount(kpDataAccount.getAddress()).getDataEntry("K2",
+ 0);
+ assertEquals(0, kv1.getVersion());
+ assertEquals(0, kv2.getVersion());
+ assertEquals("V1-0", kv1.getValue());
+ assertEquals("V2-0", kv2.getValue());
+
+ // 构建基于接口调用合约的交易请求,用于测试合约调用;
+ buildBlock(ledgerRepo, ledgerManager, opReg, new TxDefinitor() {
+ @Override
+ public void buildTx(TxBuilder txBuilder) {
+ TxTestContract contractProxy = txBuilder.contract(contractAddress, TxTestContract.class);
+ contractProxy.testRollbackWhileVersionConfliction(kpDataAccount.getAddress().toBase58(), "K1", "V1-1",
+ 0);
+ contractProxy.testRollbackWhileVersionConfliction(kpDataAccount.getAddress().toBase58(), "K2", "V2-1",
+ 0);
+ }
+ });
+ // 预期数据都能够正常写入;
+ kv1 = ledgerRepo.getDataAccountSet().getAccount(kpDataAccount.getAddress()).getDataEntry("K1", 1);
+ kv2 = ledgerRepo.getDataAccountSet().getAccount(kpDataAccount.getAddress()).getDataEntry("K2", 1);
+ assertEquals(1, kv1.getVersion());
+ assertEquals(1, kv2.getVersion());
+ assertEquals("V1-1", kv1.getValue());
+ assertEquals("V2-1", kv2.getValue());
+
+ // 构建基于接口调用合约的交易请求,用于测试合约调用;
+ buildBlock(ledgerRepo, ledgerManager, opReg, new TxDefinitor() {
+ @Override
+ public void buildTx(TxBuilder txBuilder) {
+ TxTestContract contractProxy = txBuilder.contract(contractAddress, TxTestContract.class);
+ contractProxy.testRollbackWhileVersionConfliction(kpDataAccount.getAddress().toBase58(), "K1", "V1-2",
+ 1);
+ contractProxy.testRollbackWhileVersionConfliction(kpDataAccount.getAddress().toBase58(), "K2", "V2-2",
+ 0);
+ }
+ });
+ // 预期数据都能够正常写入;
+ kv1 = ledgerRepo.getDataAccountSet().getAccount(kpDataAccount.getAddress()).getDataEntry("K1", 1);
+ assertEquals(1, kv1.getVersion());
+ assertEquals("V1-1", kv1.getValue());
+ kv1 = ledgerRepo.getDataAccountSet().getAccount(kpDataAccount.getAddress()).getDataEntry("K1", 2);
+ assertEquals(-1, kv1.getVersion());
+ assertEquals(null, kv1.getValue());
+
+ }
+
+ private LedgerBlock buildBlock(LedgerRepository ledgerRepo, LedgerService ledgerService,
+ OperationHandleRegisteration opReg, TxDefinitor txDefinitor) {
+ LedgerBlock preBlock = ledgerRepo.getLatestBlock();
+ LedgerDataQuery previousBlockDataset = ledgerRepo.getLedgerData(preBlock);
+ LedgerEditor newBlockEditor = ledgerRepo.createNextBlock();
+ TransactionBatchProcessor txbatchProcessor = new TransactionBatchProcessor(getSecurityManager(), newBlockEditor,
+ ledgerRepo, opReg);
+
+ TxBuilder txBuilder = new TxBuilder(ledgerRepo.getHash());
+ txDefinitor.buildTx(txBuilder);
+
+ TransactionRequest txReq = buildAndSignRequest(txBuilder, parti0, parti0);
+ TransactionResponse resp = txbatchProcessor.schedule(txReq);
+
+ // 提交区块;
+ TransactionBatchResultHandle txResultHandle = txbatchProcessor.prepare();
+ txResultHandle.commit();
+
+ LedgerBlock latestBlock = ledgerRepo.getLatestBlock();
+ assertNotNull(resp.getBlockHash());
+ assertEquals(preBlock.getHeight() + 1, resp.getBlockHeight());
+ return latestBlock;
+ }
+
+ private TransactionRequest buildAndSignRequest(TxBuilder txBuilder, BlockchainKeypair endpointKey,
+ BlockchainKeypair nodeKey) {
+ TransactionRequestBuilder txReqBuilder = txBuilder.prepareRequest();
+ txReqBuilder.signAsEndpoint(endpointKey);
+ txReqBuilder.signAsNode(nodeKey);
+ TransactionRequest txReq = txReqBuilder.buildRequest();
+ return txReq;
+ }
+
+ private void registerDataAccount(LedgerRepository ledgerRepo, LedgerManager ledgerManager,
+ DefaultOperationHandleRegisteration opReg, HashDigest ledgerHash, BlockchainKeypair kpDataAccount) {
+ LedgerBlock preBlock = ledgerRepo.getLatestBlock();
+ LedgerDataQuery previousBlockDataset = ledgerRepo.getLedgerData(preBlock);
+
+ // 加载合约
+ LedgerEditor newBlockEditor = ledgerRepo.createNextBlock();
+ TransactionBatchProcessor txbatchProcessor = new TransactionBatchProcessor(getSecurityManager(), newBlockEditor,
+ ledgerRepo, opReg);
+
+ // 注册数据账户;
+ TxBuilder txBuilder = new TxBuilder(ledgerHash);
+
+ txBuilder.dataAccounts().register(kpDataAccount.getIdentity());
+ TransactionRequestBuilder txReqBuilder1 = txBuilder.prepareRequest();
+ txReqBuilder1.signAsEndpoint(parti0);
+ txReqBuilder1.signAsNode(parti0);
+ TransactionRequest txReq = txReqBuilder1.buildRequest();
+
+ TransactionResponse resp = txbatchProcessor.schedule(txReq);
+
+ TransactionBatchResultHandle txResultHandle = txbatchProcessor.prepare();
+ txResultHandle.commit();
+
+ assertNotNull(resp.getBlockHash());
+ assertEquals(TransactionState.SUCCESS, resp.getExecutionState());
+ assertEquals(preBlock.getHeight() + 1, resp.getBlockHeight());
+ }
+
+ private void deploy(LedgerRepository ledgerRepo, LedgerManager ledgerManager,
+ DefaultOperationHandleRegisteration opReg, HashDigest ledgerHash, BlockchainKeypair contractKey) {
+ // 创建新区块的交易处理器;
+ LedgerBlock preBlock = ledgerRepo.getLatestBlock();
+ LedgerDataQuery previousBlockDataset = ledgerRepo.getLedgerData(preBlock);
+
+ // 加载合约
+ LedgerEditor newBlockEditor = ledgerRepo.createNextBlock();
+ LedgerSecurityManager securityManager = getSecurityManager();
+ TransactionBatchProcessor txbatchProcessor = new TransactionBatchProcessor(securityManager, newBlockEditor,
+ ledgerRepo, opReg);
+
+ // 构建基于接口调用合约的交易请求,用于测试合约调用;
+ TxBuilder txBuilder = new TxBuilder(ledgerHash);
+ txBuilder.contracts().deploy(contractKey.getIdentity(), chainCode());
+ TransactionRequestBuilder txReqBuilder = txBuilder.prepareRequest();
+ txReqBuilder.signAsEndpoint(parti0);
+ txReqBuilder.signAsNode(parti0);
+ TransactionRequest txReq = txReqBuilder.buildRequest();
+
+ TransactionResponse resp = txbatchProcessor.schedule(txReq);
+ OperationResult[] opResults = resp.getOperationResults();
+ assertNull(opResults);
+
+ // 提交区块;
+ TransactionBatchResultHandle txResultHandle = txbatchProcessor.prepare();
+ txResultHandle.commit();
+ }
+
+ private HashDigest initLedger(MemoryKVStorage storage, BlockchainKeypair... partiKeys) {
+ // 创建初始化配置;
+ LedgerInitSetting initSetting = LedgerTestUtils.createLedgerInitSetting(partiKeys);
+
+ // 创建账本;
+ LedgerEditor ldgEdt = LedgerTransactionalEditor.createEditor(initSetting, LEDGER_KEY_PREFIX, storage, storage);
+
+ TransactionRequest genesisTxReq = LedgerTestUtils.createLedgerInitTxRequest(partiKeys);
+ LedgerTransactionContext genisisTxCtx = ldgEdt.newTransaction(genesisTxReq);
+ LedgerDataset ldgDS = genisisTxCtx.getDataset();
+
+ for (int i = 0; i < partiKeys.length; i++) {
+ UserAccount userAccount = ldgDS.getUserAccountSet().register(partiKeys[i].getAddress(),
+ partiKeys[i].getPubKey());
+ userAccount.setProperty("Name", "参与方-" + i, -1);
+ userAccount.setProperty("Share", "" + (10 + i), -1);
+ }
+
+ LedgerTransaction tx = genisisTxCtx.commit(TransactionState.SUCCESS);
+
+ assertEquals(genesisTxReq.getTransactionContent().getHash(), tx.getTransactionContent().getHash());
+ assertEquals(0, tx.getBlockHeight());
+
+ LedgerBlock block = ldgEdt.prepare();
+
+ assertEquals(0, block.getHeight());
+ assertNotNull(block.getHash());
+ assertNull(block.getLedgerHash());
+ assertNull(block.getPreviousHash());
+
+ // 提交数据,写入存储;
+ ldgEdt.commit();
+
+ HashDigest ledgerHash = block.getHash();
+ return ledgerHash;
+ }
+
+ private byte[] chainCode() {
+
+ InputStream in = this.getClass().getResourceAsStream("/" + CONTRACT_JAR);
+
+ return BytesUtils.copyToBytes(in);
+ }
+
+ private static LedgerSecurityManager getSecurityManager() {
+ LedgerSecurityManager securityManager = Mockito.mock(LedgerSecurityManager.class);
+
+ SecurityPolicy securityPolicy = Mockito.mock(SecurityPolicy.class);
+ when(securityPolicy.isEndpointEnable(any(LedgerPermission.class), any())).thenReturn(true);
+ when(securityPolicy.isEndpointEnable(any(TransactionPermission.class), any())).thenReturn(true);
+ when(securityPolicy.isNodeEnable(any(LedgerPermission.class), any())).thenReturn(true);
+ when(securityPolicy.isNodeEnable(any(TransactionPermission.class), any())).thenReturn(true);
+
+ when(securityManager.createSecurityPolicy(any(), any())).thenReturn(securityPolicy);
+
+ return securityManager;
+ }
+
+ public static interface TxDefinitor {
+
+ void buildTx(TxBuilder txBuilder);
+
+ }
+}
diff --git a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerAccountTest.java b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/LedgerAccountTest.java
similarity index 89%
rename from source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerAccountTest.java
rename to source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/LedgerAccountTest.java
index 18566ca6..a50cd41e 100644
--- a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerAccountTest.java
+++ b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/LedgerAccountTest.java
@@ -1,4 +1,4 @@
-package test.com.jd.blockchain.ledger;
+package test.com.jd.blockchain.ledger.core;
import static org.junit.Assert.assertEquals;
@@ -15,7 +15,7 @@ import com.jd.blockchain.crypto.service.classic.ClassicAlgorithm;
import com.jd.blockchain.crypto.service.sm.SMAlgorithm;
import com.jd.blockchain.ledger.AccountHeader;
import com.jd.blockchain.ledger.UserInfo;
-import com.jd.blockchain.ledger.core.AccountSet;
+import com.jd.blockchain.ledger.core.MerkleAccountSet;
import com.jd.blockchain.utils.Bytes;
/**
@@ -44,7 +44,7 @@ public class LedgerAccountTest {
String address = "xxxxxxxxxxxx";
PubKey pubKey = new PubKey(SMAlgorithm.SM2, rawDigestBytes);
HashDigest hashDigest = new HashDigest(ClassicAlgorithm.SHA256, rawDigestBytes);
- AccountSet.AccountHeaderData accountHeaderData = new AccountSet.AccountHeaderData(Bytes.fromString(address),
+ MerkleAccountSet.AccountHeaderData accountHeaderData = new MerkleAccountSet.AccountHeaderData(Bytes.fromString(address),
pubKey, hashDigest);
// encode and decode
diff --git a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/LedgerAdminDatasetTest.java b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/LedgerAdminDatasetTest.java
new file mode 100644
index 00000000..e7fd2c27
--- /dev/null
+++ b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/LedgerAdminDatasetTest.java
@@ -0,0 +1,308 @@
+package test.com.jd.blockchain.ledger.core;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Arrays;
+import java.util.Random;
+
+import org.junit.Test;
+
+import com.jd.blockchain.crypto.AddressEncoding;
+import com.jd.blockchain.crypto.Crypto;
+import com.jd.blockchain.crypto.CryptoProvider;
+import com.jd.blockchain.crypto.HashDigest;
+import com.jd.blockchain.crypto.service.classic.ClassicAlgorithm;
+import com.jd.blockchain.crypto.service.classic.ClassicCryptoService;
+import com.jd.blockchain.crypto.service.sm.SMCryptoService;
+import com.jd.blockchain.ledger.BlockchainKeyGenerator;
+import com.jd.blockchain.ledger.BlockchainKeypair;
+import com.jd.blockchain.ledger.LedgerAdminInfo;
+import com.jd.blockchain.ledger.LedgerAdminSettings;
+import com.jd.blockchain.ledger.LedgerMetadata_V2;
+import com.jd.blockchain.ledger.LedgerPermission;
+import com.jd.blockchain.ledger.LedgerSettings;
+import com.jd.blockchain.ledger.ParticipantNode;
+import com.jd.blockchain.ledger.ParticipantNodeState;
+import com.jd.blockchain.ledger.RolePrivilegeSettings;
+import com.jd.blockchain.ledger.RolePrivileges;
+import com.jd.blockchain.ledger.RolesPolicy;
+import com.jd.blockchain.ledger.TransactionPermission;
+import com.jd.blockchain.ledger.UserRoles;
+import com.jd.blockchain.ledger.UserAuthorizationSettings;
+import com.jd.blockchain.ledger.core.CryptoConfig;
+import com.jd.blockchain.ledger.core.LedgerAdminDataset;
+import com.jd.blockchain.ledger.core.LedgerConfiguration;
+import com.jd.blockchain.storage.service.utils.MemoryKVStorage;
+import com.jd.blockchain.transaction.ConsensusParticipantData;
+import com.jd.blockchain.transaction.LedgerInitData;
+import com.jd.blockchain.utils.Bytes;
+import com.jd.blockchain.utils.net.NetworkAddress;
+
+public class LedgerAdminDatasetTest {
+
+ private static final String[] SUPPORTED_PROVIDERS = { ClassicCryptoService.class.getName(),
+ SMCryptoService.class.getName() };
+
+ private Random rand = new Random();
+
+ @Test
+ public void testSerialization() {
+ String keyPrefix = "";
+ LedgerInitData initSetting = new LedgerInitData();
+ ConsensusParticipantData[] parties = new ConsensusParticipantData[5];
+ BlockchainKeypair[] bckeys = new BlockchainKeypair[parties.length];
+ for (int i = 0; i < parties.length; i++) {
+ bckeys[i] = BlockchainKeyGenerator.getInstance().generate();
+ parties[i] = new ConsensusParticipantData();
+ parties[i].setId(i);
+ parties[i].setAddress(AddressEncoding.generateAddress(bckeys[i].getPubKey()));
+ parties[i].setHostAddress(new NetworkAddress("192.168.10." + (10 + i), 10010 + 10 * i));
+ parties[i].setName("Participant[" + i + "]");
+ parties[i].setPubKey(bckeys[i].getPubKey());
+ parties[i].setParticipantState(ParticipantNodeState.ACTIVED);
+ }
+ ConsensusParticipantData[] parties1 = Arrays.copyOf(parties, 4);
+ initSetting.setConsensusParticipants(parties1);
+
+ byte[] csSysSettingBytes = new byte[64];
+ rand.nextBytes(csSysSettingBytes);
+ initSetting.setConsensusSettings(new Bytes(csSysSettingBytes));
+ initSetting.setConsensusProvider("consensus-provider");
+
+ 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(true);
+ cryptoSetting.setHashAlgorithm(ClassicAlgorithm.SHA256);
+ initSetting.setCryptoSetting(cryptoSetting);
+
+ byte[] ledgerSeed = new byte[16];
+ rand.nextBytes(ledgerSeed);
+ initSetting.setLedgerSeed(ledgerSeed);
+
+ MemoryKVStorage testStorage = new MemoryKVStorage();
+
+ // Create intance with init setting;
+ LedgerAdminDataset ledgerAdminDataset = new LedgerAdminDataset(initSetting, keyPrefix, testStorage,
+ testStorage);
+
+ ledgerAdminDataset.getRolePrivileges().addRolePrivilege("DEFAULT",
+ new LedgerPermission[] { LedgerPermission.CONFIGURE_ROLES, LedgerPermission.REGISTER_USER,
+ LedgerPermission.APPROVE_TX },
+ new TransactionPermission[] { TransactionPermission.DIRECT_OPERATION,
+ TransactionPermission.CONTRACT_OPERATION });
+
+ ledgerAdminDataset.getAuthorizations().addUserRoles(parties[0].getAddress(), RolesPolicy.UNION, "DEFAULT");
+
+ // New created instance is updated until being committed;
+ assertTrue(ledgerAdminDataset.isUpdated());
+ // Hash of account is null until being committed;
+ assertNull(ledgerAdminDataset.getHash());
+
+ LedgerMetadata_V2 meta = ledgerAdminDataset.getMetadata();
+ assertNull(meta.getParticipantsHash());
+
+ // Commit, and check the storage keys;
+ ledgerAdminDataset.commit();
+
+ // New created instance isn't updated after being committed;
+ assertFalse(ledgerAdminDataset.isUpdated());
+ // Hash of account isn't null after being committed;
+ assertNotNull(ledgerAdminDataset.getHash());
+
+ meta = ledgerAdminDataset.getMetadata();
+ assertNotNull(meta.getParticipantsHash());
+ assertNotNull(meta.getSettingsHash());
+ assertNotNull(meta.getRolePrivilegesHash());
+ assertNotNull(meta.getUserRolesHash());
+
+ assertNotNull(ledgerAdminDataset.getRolePrivileges().getRolePrivilege("DEFAULT"));
+
+ // ----------------------
+ // Reload account from storage with readonly mode, and check the integrity of
+ // data;
+ HashDigest adminAccHash = ledgerAdminDataset.getHash();
+ LedgerAdminDataset reloadAdminAccount1 = new LedgerAdminDataset(adminAccHash, keyPrefix, testStorage,
+ testStorage, true);
+
+ LedgerMetadata_V2 meta2 = reloadAdminAccount1.getMetadata();
+ assertNotNull(meta2.getParticipantsHash());
+ assertNotNull(meta2.getSettingsHash());
+ assertNotNull(meta2.getRolePrivilegesHash());
+ assertNotNull(meta2.getUserRolesHash());
+
+ // verify realod settings of admin account;
+ verifyRealoadingSettings(reloadAdminAccount1, adminAccHash, ledgerAdminDataset.getMetadata(),
+ ledgerAdminDataset.getSettings());
+ // verify the consensus participant list;
+ verifyRealoadingParities(reloadAdminAccount1, parties1);
+ // It will throw exeception because of this account is readonly;
+ verifyReadonlyState(reloadAdminAccount1);
+
+ verifyRealoadingRoleAuthorizations(reloadAdminAccount1, ledgerAdminDataset.getRolePrivileges(),
+ ledgerAdminDataset.getAuthorizations());
+
+ // --------------
+ // 重新加载,并进行修改;
+ LedgerAdminDataset reloadAdminAccount2 = new LedgerAdminDataset(adminAccHash, keyPrefix, testStorage, testStorage, false);
+ LedgerConfiguration newSetting = new LedgerConfiguration(reloadAdminAccount2.getPreviousSetting());
+ byte[] newCsSettingBytes = new byte[64];
+ rand.nextBytes(newCsSettingBytes);
+ newSetting.setConsensusSetting(new Bytes(newCsSettingBytes));
+ newSetting.getCryptoSetting().setAutoVerifyHash(false);
+ reloadAdminAccount2.setLedgerSetting(newSetting);
+
+ reloadAdminAccount2.addParticipant(parties[4]);
+
+ reloadAdminAccount2.getRolePrivileges().addRolePrivilege("ADMIN",
+ new LedgerPermission[] { LedgerPermission.APPROVE_TX },
+ new TransactionPermission[] { TransactionPermission.DIRECT_OPERATION });
+
+ reloadAdminAccount2.getRolePrivileges().disablePermissions("DEFAULT", TransactionPermission.CONTRACT_OPERATION);
+
+ reloadAdminAccount2.getAuthorizations().addUserRoles(parties[1].getAddress(), RolesPolicy.UNION, "DEFAULT", "ADMIN");
+
+ reloadAdminAccount2.commit();
+
+ LedgerSettings newlyLedgerSettings = reloadAdminAccount2.getSettings();
+
+ // record the new account hash;
+ HashDigest newAccHash = reloadAdminAccount2.getHash();
+ LedgerMetadata_V2 newMeta = reloadAdminAccount2.getMetadata();
+
+ // load the last version of account and verify again;
+ LedgerAdminDataset previousAdminAccount = new LedgerAdminDataset(adminAccHash, keyPrefix, testStorage,
+ testStorage, true);
+ verifyRealoadingSettings(previousAdminAccount, adminAccHash, ledgerAdminDataset.getMetadata(),
+ ledgerAdminDataset.getSettings());
+ verifyRealoadingParities(previousAdminAccount, parties1);
+ verifyReadonlyState(previousAdminAccount);
+
+ // load the hash of new committing;
+ LedgerAdminDataset newlyAdminAccount = new LedgerAdminDataset(newAccHash, keyPrefix, testStorage, testStorage,
+ true);
+ verifyRealoadingSettings(newlyAdminAccount, newAccHash, newMeta, newlyLedgerSettings);
+ verifyRealoadingParities(newlyAdminAccount, parties);
+ verifyReadonlyState(newlyAdminAccount);
+
+// System.out.println("========= [LedgerAdminAccount Test] Show generated storage keys... =======");
+// testStorage.printStoragedKeys();
+ }
+
+ private void verifyRealoadingSettings(LedgerAdminDataset actualAccount, HashDigest expAccRootHash,
+ LedgerMetadata_V2 expMeta, LedgerSettings expLedgerSettings) {
+ // 验证基本信息;
+ assertFalse(actualAccount.isUpdated());
+ assertTrue(actualAccount.isReadonly());
+
+ assertEquals(expAccRootHash, actualAccount.getHash());
+
+ // verify metadata;
+ LedgerMetadata_V2 actualMeta = actualAccount.getMetadata();
+ assertArrayEquals(expMeta.getSeed(), actualMeta.getSeed());
+ assertEquals(expMeta.getParticipantsHash(), actualMeta.getParticipantsHash());
+ assertNotNull(actualMeta.getSettingsHash());
+ assertEquals(expMeta.getSettingsHash(), actualMeta.getSettingsHash());
+ assertNotNull(actualMeta.getRolePrivilegesHash());
+ assertEquals(expMeta.getRolePrivilegesHash(), actualMeta.getRolePrivilegesHash());
+ assertNotNull(actualMeta.getUserRolesHash());
+ assertEquals(expMeta.getUserRolesHash(), actualMeta.getUserRolesHash());
+
+ LedgerSettings actualLedgerSettings = actualAccount.getSettings();
+
+ assertEquals(expLedgerSettings.getConsensusSetting(), actualLedgerSettings.getConsensusSetting());
+ assertEquals(expLedgerSettings.getConsensusProvider(), actualLedgerSettings.getConsensusProvider());
+
+ assertEquals(expLedgerSettings.getCryptoSetting().getAutoVerifyHash(),
+ actualLedgerSettings.getCryptoSetting().getAutoVerifyHash());
+ assertEquals(expLedgerSettings.getCryptoSetting().getHashAlgorithm(),
+ actualLedgerSettings.getCryptoSetting().getHashAlgorithm());
+ }
+
+ private void verifyRealoadingRoleAuthorizations(LedgerAdminSettings actualAccount,
+ RolePrivilegeSettings expRolePrivilegeSettings, UserAuthorizationSettings expUserRoleSettings) {
+ // 验证基本信息;
+ RolePrivilegeSettings actualRolePrivileges = actualAccount.getRolePrivileges();
+ RolePrivileges[] expRPs = expRolePrivilegeSettings.getRolePrivileges();
+
+ assertEquals(expRPs.length, actualRolePrivileges.getRoleCount());
+
+ for (RolePrivileges expRP : expRPs) {
+ RolePrivileges actualRP = actualRolePrivileges.getRolePrivilege(expRP.getRoleName());
+ assertNotNull(actualRP);
+ assertArrayEquals(expRP.getLedgerPrivilege().toBytes(), actualRP.getLedgerPrivilege().toBytes());
+ assertArrayEquals(expRP.getTransactionPrivilege().toBytes(), actualRP.getTransactionPrivilege().toBytes());
+ }
+
+ UserAuthorizationSettings actualUserRoleSettings = actualAccount.getAuthorizations();
+ UserRoles[] expUserRoles = expUserRoleSettings.getUserRoles();
+ assertEquals(expUserRoles.length, actualUserRoleSettings.getUserCount());
+
+ for (UserRoles expUR : expUserRoles) {
+ UserRoles actualUR = actualAccount.getAuthorizations().getUserRoles(expUR.getUserAddress());
+ assertNotNull(actualUR);
+ assertEquals(expUR.getPolicy(), actualUR.getPolicy());
+ String[] expRoles = expUR.getRoles();
+ Arrays.sort(expRoles);
+ String[] actualRoles = actualUR.getRoles();
+ Arrays.sort(actualRoles);
+ assertArrayEquals(expRoles, actualRoles);
+ }
+ }
+
+ private void verifyRealoadingParities(LedgerAdminInfo actualAccount, ParticipantNode[] expParties) {
+ assertEquals(expParties.length, actualAccount.getParticipantCount());
+ ParticipantNode[] actualPaticipants = actualAccount.getParticipants();
+ assertEquals(expParties.length, actualPaticipants.length);
+ for (int i = 0; i < actualPaticipants.length; i++) {
+ ParticipantNode rlParti = actualPaticipants[i];
+ assertEquals(expParties[i].getAddress(), rlParti.getAddress());
+ assertEquals(expParties[i].getName(), rlParti.getName());
+ // assertEquals(expParties[i].getConsensusAddress(),
+ // rlParti.getConsensusAddress());
+ assertEquals(expParties[i].getPubKey(), rlParti.getPubKey());
+ }
+ }
+
+ /**
+ * 验证指定账户是否只读;
+ *
+ * @param readonlyAccount
+ */
+ private void verifyReadonlyState(LedgerAdminDataset readonlyAccount) {
+ ConsensusParticipantData newParti = new ConsensusParticipantData();
+ newParti.setId((int) readonlyAccount.getParticipantCount());
+ newParti.setHostAddress(
+ new NetworkAddress("192.168.10." + (10 + newParti.getId()), 10010 + 10 * newParti.getId()));
+ newParti.setName("Participant[" + newParti.getAddress() + "]");
+
+ BlockchainKeypair newKey = BlockchainKeyGenerator.getInstance().generate();
+ newParti.setPubKey(newKey.getPubKey());
+
+ Throwable ex = null;
+ try {
+ readonlyAccount.addParticipant(newParti);
+ } catch (Exception e) {
+ ex = e;
+ }
+ assertNotNull(ex);
+
+ ex = null;
+ try {
+ LedgerConfiguration newLedgerSetting = new LedgerConfiguration(readonlyAccount.getSettings());
+ readonlyAccount.setLedgerSetting(newLedgerSetting);
+ } catch (Exception e) {
+ ex = e;
+ }
+ assertNotNull(ex);
+ }
+
+}
diff --git a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerBlockImplTest.java b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/LedgerBlockImplTest.java
similarity index 96%
rename from source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerBlockImplTest.java
rename to source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/LedgerBlockImplTest.java
index ce29e1a5..9479cc2b 100644
--- a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerBlockImplTest.java
+++ b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/LedgerBlockImplTest.java
@@ -6,7 +6,7 @@
* Date: 2018/8/30 上午10:45
* Description:
*/
-package test.com.jd.blockchain.ledger;
+package test.com.jd.blockchain.ledger.core;
import static org.junit.Assert.assertEquals;
@@ -19,8 +19,8 @@ import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.crypto.service.classic.ClassicAlgorithm;
import com.jd.blockchain.ledger.LedgerBlock;
import com.jd.blockchain.ledger.LedgerDataSnapshot;
-import com.jd.blockchain.ledger.core.impl.LedgerBlockData;
-import com.jd.blockchain.ledger.core.impl.TransactionStagedSnapshot;
+import com.jd.blockchain.ledger.core.LedgerBlockData;
+import com.jd.blockchain.ledger.core.TransactionStagedSnapshot;
/**
*
diff --git a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerEditorTest.java b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/LedgerEditorTest.java
similarity index 94%
rename from source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerEditorTest.java
rename to source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/LedgerEditorTest.java
index 0779204e..97979205 100644
--- a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerEditorTest.java
+++ b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/LedgerEditorTest.java
@@ -1,4 +1,4 @@
-package test.com.jd.blockchain.ledger;
+package test.com.jd.blockchain.ledger.core;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
@@ -27,14 +27,14 @@ import com.jd.blockchain.ledger.TransactionRequest;
import com.jd.blockchain.ledger.TransactionState;
import com.jd.blockchain.ledger.core.CryptoConfig;
import com.jd.blockchain.ledger.core.DataAccount;
-import com.jd.blockchain.ledger.core.LedgerDataSet;
+import com.jd.blockchain.ledger.core.LedgerDataset;
import com.jd.blockchain.ledger.core.LedgerEditor;
import com.jd.blockchain.ledger.core.LedgerTransactionContext;
+import com.jd.blockchain.ledger.core.LedgerTransactionalEditor;
import com.jd.blockchain.ledger.core.UserAccount;
-import com.jd.blockchain.ledger.core.impl.LedgerTransactionalEditor;
import com.jd.blockchain.storage.service.utils.MemoryKVStorage;
import com.jd.blockchain.transaction.ConsensusParticipantData;
-import com.jd.blockchain.transaction.LedgerInitSettingData;
+import com.jd.blockchain.transaction.LedgerInitData;
import com.jd.blockchain.utils.Bytes;
import com.jd.blockchain.utils.io.BytesUtils;
import com.jd.blockchain.utils.net.NetworkAddress;
@@ -95,7 +95,7 @@ public class LedgerEditorTest {
public void testWriteDataAccoutKvOp() {
LedgerEditor ldgEdt = createLedgerInitEditor();
LedgerTransactionContext genisisTxCtx = createGenisisTx(ldgEdt, participants);
- LedgerDataSet ldgDS = genisisTxCtx.getDataSet();
+ LedgerDataset ldgDS = genisisTxCtx.getDataset();
AsymmetricKeypair cryptoKeyPair = signatureFunction.generateKeypair();
BlockchainKeypair dataKP = new BlockchainKeypair(cryptoKeyPair.getPubKey(), cryptoKeyPair.getPrivKey());
@@ -128,7 +128,7 @@ public class LedgerEditorTest {
public void testGennesisBlockCreation() {
LedgerEditor ldgEdt = createLedgerInitEditor();
LedgerTransactionContext genisisTxCtx = createGenisisTx(ldgEdt, participants);
- LedgerDataSet ldgDS = genisisTxCtx.getDataSet();
+ LedgerDataset ldgDS = genisisTxCtx.getDataset();
AsymmetricKeypair cryptoKeyPair = signatureFunction.generateKeypair();
BlockchainKeypair userKP = new BlockchainKeypair(cryptoKeyPair.getPubKey(), cryptoKeyPair.getPrivKey());
diff --git a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerInitOperationTest.java b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/LedgerInitOperationTest.java
similarity index 92%
rename from source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerInitOperationTest.java
rename to source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/LedgerInitOperationTest.java
index 9cee71df..e916cc66 100644
--- a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerInitOperationTest.java
+++ b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/LedgerInitOperationTest.java
@@ -1,4 +1,4 @@
-package test.com.jd.blockchain.ledger;
+package test.com.jd.blockchain.ledger.core;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
@@ -6,6 +6,7 @@ import static org.junit.Assert.assertEquals;
import java.util.Arrays;
import java.util.Random;
+import com.jd.blockchain.ledger.*;
import org.junit.Before;
import org.junit.Test;
@@ -17,15 +18,11 @@ import com.jd.blockchain.crypto.CryptoProvider;
import com.jd.blockchain.crypto.service.classic.ClassicAlgorithm;
import com.jd.blockchain.crypto.service.classic.ClassicCryptoService;
import com.jd.blockchain.crypto.service.sm.SMCryptoService;
-import com.jd.blockchain.ledger.BlockchainKeyGenerator;
-import com.jd.blockchain.ledger.BlockchainKeypair;
-import com.jd.blockchain.ledger.LedgerInitOperation;
-import com.jd.blockchain.ledger.LedgerInitSetting;
import com.jd.blockchain.ledger.core.CryptoConfig;
import com.jd.blockchain.ledger.core.ParticipantCertData;
import com.jd.blockchain.transaction.ConsensusParticipantData;
import com.jd.blockchain.transaction.LedgerInitOpTemplate;
-import com.jd.blockchain.transaction.LedgerInitSettingData;
+import com.jd.blockchain.transaction.LedgerInitData;
import com.jd.blockchain.utils.Bytes;
import com.jd.blockchain.utils.net.NetworkAddress;
@@ -36,7 +33,7 @@ public class LedgerInitOperationTest {
byte[] seed = null;
byte[] csSysSettingBytes = null;
- LedgerInitSettingData ledgerInitSettingData = new LedgerInitSettingData();
+ LedgerInitData ledgerInitSettingData = new LedgerInitData();
@Before
public void initCfg() {
@@ -76,10 +73,11 @@ public class LedgerInitOperationTest {
keys[i] = BlockchainKeyGenerator.getInstance().generate();
parties[i] = new ConsensusParticipantData();
// parties[i].setId(i);
- parties[i].setAddress(AddressEncoding.generateAddress(keys[i].getPubKey()).toBase58());
+ parties[i].setAddress(AddressEncoding.generateAddress(keys[i].getPubKey()));
parties[i].setHostAddress(new NetworkAddress("192.168.10." + (10 + i), 10010 + 10 * i));
parties[i].setName("Participant[" + i + "]");
parties[i].setPubKey(keys[i].getPubKey());
+ parties[i].setParticipantState(ParticipantNodeState.ACTIVED);
}
ConsensusParticipantData[] parties1 = Arrays.copyOf(parties, 4);
@@ -117,8 +115,8 @@ public class LedgerInitOperationTest {
for (int i = 0; i < parties.length; i++) {
keys[i] = BlockchainKeyGenerator.getInstance().generate();
- parties[i] = new ParticipantCertData(AddressEncoding.generateAddress(keys[i].getPubKey()).toBase58(),
- "Participant[" + i + "]", keys[i].getPubKey());
+ parties[i] = new ParticipantCertData(AddressEncoding.generateAddress(keys[i].getPubKey()),
+ "Participant[" + i + "]", keys[i].getPubKey(), ParticipantNodeState.ACTIVED);
}
ParticipantCertData[] parties1 = Arrays.copyOf(parties, 4);
diff --git a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerInitSettingSerializeTest.java b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/LedgerInitSettingSerializeTest.java
similarity index 93%
rename from source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerInitSettingSerializeTest.java
rename to source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/LedgerInitSettingSerializeTest.java
index f867ae9b..3884186e 100644
--- a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerInitSettingSerializeTest.java
+++ b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/LedgerInitSettingSerializeTest.java
@@ -1,4 +1,4 @@
-package test.com.jd.blockchain.ledger;
+package test.com.jd.blockchain.ledger.core;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
@@ -6,6 +6,7 @@ import static org.junit.Assert.assertEquals;
import java.util.Arrays;
import java.util.Random;
+import com.jd.blockchain.ledger.ParticipantNodeState;
import org.junit.Before;
import org.junit.Test;
@@ -24,14 +25,14 @@ import com.jd.blockchain.ledger.core.CryptoConfig;
import com.jd.blockchain.ledger.core.ParticipantCertData;
import com.jd.blockchain.transaction.ConsensusParticipantData;
import com.jd.blockchain.transaction.LedgerInitOpTemplate;
-import com.jd.blockchain.transaction.LedgerInitSettingData;
+import com.jd.blockchain.transaction.LedgerInitData;
import com.jd.blockchain.utils.Bytes;
import com.jd.blockchain.utils.net.NetworkAddress;
public class LedgerInitSettingSerializeTest {
byte[] seed = null;
byte[] csSysSettingBytes = null;
- LedgerInitSettingData ledgerInitSettingData = new LedgerInitSettingData();
+ LedgerInitData ledgerInitSettingData = new LedgerInitData();
LedgerInitOpTemplate template = new LedgerInitOpTemplate();
private static final String[] SUPPORTED_PROVIDERS = { ClassicCryptoService.class.getName(),
@@ -76,15 +77,16 @@ public class LedgerInitSettingSerializeTest {
keys[i] = BlockchainKeyGenerator.getInstance().generate();
parties[i] = new ConsensusParticipantData();
// parties[i].setId(i);
- parties[i].setAddress(AddressEncoding.generateAddress(keys[i].getPubKey()).toBase58());
+ parties[i].setAddress(AddressEncoding.generateAddress(keys[i].getPubKey()));
parties[i].setHostAddress(new NetworkAddress("192.168.10." + (10 + i), 10010 + 10 * i));
parties[i].setName("Participant[" + i + "]");
parties[i].setPubKey(keys[i].getPubKey());
+ parties[i].setParticipantState(ParticipantNodeState.ACTIVED);
}
ConsensusParticipantData[] parties1 = Arrays.copyOf(parties, 4);
ledgerInitSettingData.setConsensusParticipants(parties1);
-
+
byte[] encode = BinaryProtocol.encode(ledgerInitSettingData, LedgerInitSetting.class);
LedgerInitSetting decode = BinaryProtocol.decode(encode);
@@ -121,8 +123,8 @@ public class LedgerInitSettingSerializeTest {
for (int i = 0; i < parties.length; i++) {
keys[i] = BlockchainKeyGenerator.getInstance().generate();
- parties[i] = new ParticipantCertData(AddressEncoding.generateAddress(keys[i].getPubKey()).toBase58(),
- "Participant[" + i + "]", keys[i].getPubKey());
+ parties[i] = new ParticipantCertData(AddressEncoding.generateAddress(keys[i].getPubKey()),
+ "Participant[" + i + "]", keys[i].getPubKey(), ParticipantNodeState.ACTIVED);
}
ParticipantCertData[] parties1 = Arrays.copyOf(parties, 4);
diff --git a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerManagerTest.java b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/LedgerManagerTest.java
similarity index 83%
rename from source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerManagerTest.java
rename to source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/LedgerManagerTest.java
index dfc17f24..225bd16d 100644
--- a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerManagerTest.java
+++ b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/LedgerManagerTest.java
@@ -1,4 +1,4 @@
-package test.com.jd.blockchain.ledger;
+package test.com.jd.blockchain.ledger.core;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
@@ -6,6 +6,7 @@ import static org.junit.Assert.assertNull;
import java.util.stream.Stream;
+import com.jd.blockchain.ledger.*;
import org.junit.Before;
import org.junit.Test;
@@ -19,32 +20,20 @@ import com.jd.blockchain.crypto.SignatureFunction;
import com.jd.blockchain.crypto.service.classic.ClassicAlgorithm;
import com.jd.blockchain.crypto.service.classic.ClassicCryptoService;
import com.jd.blockchain.crypto.service.sm.SMCryptoService;
-import com.jd.blockchain.ledger.BlockBody;
-import com.jd.blockchain.ledger.BlockchainKeyGenerator;
-import com.jd.blockchain.ledger.BlockchainKeypair;
-import com.jd.blockchain.ledger.DataAccountRegisterOperation;
-import com.jd.blockchain.ledger.DigitalSignature;
-import com.jd.blockchain.ledger.LedgerBlock;
-import com.jd.blockchain.ledger.LedgerInitSetting;
-import com.jd.blockchain.ledger.LedgerTransaction;
-import com.jd.blockchain.ledger.TransactionContent;
-import com.jd.blockchain.ledger.TransactionRequest;
-import com.jd.blockchain.ledger.TransactionRequestBuilder;
-import com.jd.blockchain.ledger.TransactionState;
-import com.jd.blockchain.ledger.UserRegisterOperation;
-import com.jd.blockchain.ledger.core.ContractAccountSet;
+import com.jd.blockchain.ledger.core.ContractAccountQuery;
import com.jd.blockchain.ledger.core.CryptoConfig;
-import com.jd.blockchain.ledger.core.DataAccountSet;
-import com.jd.blockchain.ledger.core.LedgerDataSet;
+import com.jd.blockchain.ledger.core.DataAccountQuery;
+import com.jd.blockchain.ledger.core.LedgerDataset;
import com.jd.blockchain.ledger.core.LedgerEditor;
+import com.jd.blockchain.ledger.core.LedgerInitializer;
+import com.jd.blockchain.ledger.core.LedgerManager;
import com.jd.blockchain.ledger.core.LedgerRepository;
import com.jd.blockchain.ledger.core.LedgerTransactionContext;
import com.jd.blockchain.ledger.core.UserAccount;
-import com.jd.blockchain.ledger.core.UserAccountSet;
-import com.jd.blockchain.ledger.core.impl.LedgerManager;
+import com.jd.blockchain.ledger.core.UserAccountQuery;
import com.jd.blockchain.storage.service.utils.MemoryKVStorage;
import com.jd.blockchain.transaction.ConsensusParticipantData;
-import com.jd.blockchain.transaction.LedgerInitSettingData;
+import com.jd.blockchain.transaction.LedgerInitData;
import com.jd.blockchain.transaction.TxBuilder;
import com.jd.blockchain.utils.Bytes;
import com.jd.blockchain.utils.io.BytesUtils;
@@ -56,6 +45,9 @@ public class LedgerManagerTest {
DataContractRegistry.register(TransactionContent.class);
DataContractRegistry.register(UserRegisterOperation.class);
DataContractRegistry.register(DataAccountRegisterOperation.class);
+ DataContractRegistry.register(ParticipantNode.class);
+ DataContractRegistry.register(ParticipantRegisterOperation.class);
+ DataContractRegistry.register(ParticipantStateUpdateOperation.class);
DataContractRegistry.register(BlockBody.class);
DataContractRegistry.register(CryptoProvider.class);
}
@@ -81,20 +73,19 @@ public class LedgerManagerTest {
public void testLedgerInit() {
// 创建账本初始化配置;
LedgerInitSetting initSetting = createLedgerInitSetting();
-
+
// 采用基于内存的 Storage;
MemoryKVStorage storage = new MemoryKVStorage();
// 新建账本;
- LedgerManager ledgerManager = new LedgerManager();
- LedgerEditor ldgEdt = ledgerManager.newLedger(initSetting, storage);
+ LedgerEditor ldgEdt = LedgerInitializer.createLedgerEditor(initSetting, storage);
// 创建一个模拟的创世交易;
TransactionRequest genesisTxReq = LedgerTestUtils.createLedgerInitTxRequest(participants);
// 记录交易,注册用户;
LedgerTransactionContext txCtx = ldgEdt.newTransaction(genesisTxReq);
- LedgerDataSet ldgDS = txCtx.getDataSet();
+ LedgerDataset ldgDS = txCtx.getDataset();
BlockchainKeypair userKP = BlockchainKeyGenerator.getInstance().generate();
UserAccount userAccount = ldgDS.getUserAccountSet().register(userKP.getAddress(), userKP.getPubKey());
@@ -121,6 +112,9 @@ public class LedgerManagerTest {
// 提交数据,写入存储;
ldgEdt.commit();
+
+ assertNull(genesisBlock.getLedgerHash());
+ assertNotNull(genesisBlock.getHash());
// 重新加载并校验结果;
LedgerManager reloadLedgerManager = new LedgerManager();
@@ -145,7 +139,7 @@ public class LedgerManagerTest {
TransactionRequest txRequest = txReqBuilder.buildRequest();
LedgerTransactionContext txCtx1 = editor1.newTransaction(txRequest);
- txCtx1.getDataSet().getDataAccountSet().register(dataKey.getAddress(), dataKey.getPubKey(), null);
+ txCtx1.getDataset().getDataAccountSet().register(dataKey.getAddress(), dataKey.getPubKey(), null);
txCtx1.commit(TransactionState.SUCCESS);
LedgerBlock block1 = editor1.prepare();
@@ -167,9 +161,9 @@ public class LedgerManagerTest {
assertEquals(1, latestBlock.getHeight());
assertEquals(block1.getHash(), latestBlock.getHash());
- DataAccountSet dataAccountSet = reloadLedgerRepo.getDataAccountSet(latestBlock);
- UserAccountSet userAccountSet = reloadLedgerRepo.getUserAccountSet(latestBlock);
- ContractAccountSet contractAccountSet = reloadLedgerRepo.getContractAccountSet(latestBlock);
+ DataAccountQuery dataAccountSet = reloadLedgerRepo.getDataAccountSet(latestBlock);
+ UserAccountQuery userAccountSet = reloadLedgerRepo.getUserAccountSet(latestBlock);
+ ContractAccountQuery contractAccountSet = reloadLedgerRepo.getContractAccountSet(latestBlock);
}
@@ -199,7 +193,7 @@ public class LedgerManagerTest {
defCryptoSetting.setAutoVerifyHash(true);
defCryptoSetting.setHashAlgorithm(ClassicAlgorithm.SHA256);
- LedgerInitSettingData initSetting = new LedgerInitSettingData();
+ LedgerInitData initSetting = new LedgerInitData();
initSetting.setLedgerSeed(BytesUtils.toBytes("A Test Ledger seed!", "UTF-8"));
initSetting.setCryptoSetting(defCryptoSetting);
@@ -209,32 +203,36 @@ public class LedgerManagerTest {
parties[0].setName("John");
AsymmetricKeypair kp0 = signatureFunction.generateKeypair();
parties[0].setPubKey(kp0.getPubKey());
- parties[0].setAddress(AddressEncoding.generateAddress(kp0.getPubKey()).toBase58());
+ parties[0].setAddress(AddressEncoding.generateAddress(kp0.getPubKey()));
parties[0].setHostAddress(new NetworkAddress("127.0.0.1", 9000));
+ parties[0].setParticipantState(ParticipantNodeState.ACTIVED);
parties[1] = new ConsensusParticipantData();
parties[1].setId(1);
parties[1].setName("Mary");
AsymmetricKeypair kp1 = signatureFunction.generateKeypair();
parties[1].setPubKey(kp1.getPubKey());
- parties[1].setAddress(AddressEncoding.generateAddress(kp1.getPubKey()).toBase58());
+ parties[1].setAddress(AddressEncoding.generateAddress(kp1.getPubKey()));
parties[1].setHostAddress(new NetworkAddress("127.0.0.1", 9010));
+ parties[1].setParticipantState(ParticipantNodeState.ACTIVED);
parties[2] = new ConsensusParticipantData();
parties[2].setId(2);
parties[2].setName("Jerry");
AsymmetricKeypair kp2 = signatureFunction.generateKeypair();
parties[2].setPubKey(kp2.getPubKey());
- parties[2].setAddress(AddressEncoding.generateAddress(kp2.getPubKey()).toBase58());
+ parties[2].setAddress(AddressEncoding.generateAddress(kp2.getPubKey()));
parties[2].setHostAddress(new NetworkAddress("127.0.0.1", 9020));
+ parties[2].setParticipantState(ParticipantNodeState.ACTIVED);
parties[3] = new ConsensusParticipantData();
parties[3].setId(3);
parties[3].setName("Tom");
AsymmetricKeypair kp3 = signatureFunction.generateKeypair();
parties[3].setPubKey(kp3.getPubKey());
- parties[3].setAddress(AddressEncoding.generateAddress(kp3.getPubKey()).toBase58());
+ parties[3].setAddress(AddressEncoding.generateAddress(kp3.getPubKey()));
parties[3].setHostAddress(new NetworkAddress("127.0.0.1", 9030));
+ parties[3].setParticipantState(ParticipantNodeState.ACTIVED);
initSetting.setConsensusParticipants(parties);
diff --git a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerMetaDataTest.java b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/LedgerMetaDataTest.java
similarity index 90%
rename from source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerMetaDataTest.java
rename to source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/LedgerMetaDataTest.java
index 401c5de2..51254613 100644
--- a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerMetaDataTest.java
+++ b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/LedgerMetaDataTest.java
@@ -1,4 +1,4 @@
-package test.com.jd.blockchain.ledger;
+package test.com.jd.blockchain.ledger.core;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
@@ -7,8 +7,7 @@ import static org.junit.Assert.assertTrue;
import java.util.Random;
-import com.jd.blockchain.ledger.LedgerMetadata;
-import com.jd.blockchain.ledger.LedgerSetting;
+import com.jd.blockchain.ledger.*;
import org.junit.Before;
import org.junit.Test;
@@ -16,16 +15,15 @@ import com.jd.blockchain.binaryproto.BinaryProtocol;
import com.jd.blockchain.binaryproto.DataContractRegistry;
import com.jd.blockchain.crypto.AddressEncoding;
import com.jd.blockchain.crypto.Crypto;
+import com.jd.blockchain.crypto.CryptoAlgorithm;
import com.jd.blockchain.crypto.CryptoProvider;
import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.crypto.PubKey;
import com.jd.blockchain.crypto.service.classic.ClassicAlgorithm;
import com.jd.blockchain.crypto.service.classic.ClassicCryptoService;
import com.jd.blockchain.crypto.service.sm.SMCryptoService;
-import com.jd.blockchain.ledger.CryptoSetting;
-import com.jd.blockchain.ledger.ParticipantNode;
import com.jd.blockchain.ledger.core.CryptoConfig;
-import com.jd.blockchain.ledger.core.LedgerAdminAccount;
+import com.jd.blockchain.ledger.core.LedgerAdminDataset;
import com.jd.blockchain.ledger.core.LedgerConfiguration;
import com.jd.blockchain.ledger.core.ParticipantCertData;
import com.jd.blockchain.utils.Bytes;
@@ -74,12 +72,14 @@ public class LedgerMetaDataTest {
cryptoConfig.setAutoVerifyHash(true);
cryptoConfig.setHashAlgorithm(ClassicAlgorithm.SHA256);
- LedgerConfiguration ledgerConfiguration = new LedgerConfiguration(consensusProvider,
- new Bytes(consensusSettingBytes), cryptoConfig);
- LedgerAdminAccount.LedgerMetadataImpl ledgerMetadata = new LedgerAdminAccount.LedgerMetadataImpl();
+// LedgerConfiguration ledgerConfiguration = new LedgerConfiguration(consensusProvider,
+// new Bytes(consensusSettingBytes), cryptoConfig);
+ HashDigest settingsHash = Crypto.getHashFunction("SHA256").hash(consensusSettingBytes);
+
+ LedgerAdminDataset.LedgerMetadataInfo ledgerMetadata = new LedgerAdminDataset.LedgerMetadataInfo();
ledgerMetadata.setSeed(seed);
- ledgerMetadata.setSetting(ledgerConfiguration);
+ ledgerMetadata.setSettingsHash(settingsHash);
HashDigest hashDigest = new HashDigest(ClassicAlgorithm.SHA256, rawDigestBytes);
ledgerMetadata.setParticipantsHash(hashDigest);
@@ -91,7 +91,7 @@ public class LedgerMetaDataTest {
// verify start
assertArrayEquals(ledgerMetadata.getSeed(), deLedgerMetaData.getSeed());
assertEquals(ledgerMetadata.getParticipantsHash(), deLedgerMetaData.getParticipantsHash());
- assertNotEquals(ledgerMetadata.getSetting(), deLedgerMetaData.getSetting());
+ assertEquals(ledgerMetadata.getSettingsHash(), deLedgerMetaData.getSettingsHash());
return;
}
@@ -119,8 +119,8 @@ public class LedgerMetaDataTest {
LedgerConfiguration ledgerConfiguration = new LedgerConfiguration(consensusProvider, new Bytes(csSettingsBytes),
cryptoConfig);
- byte[] encodeBytes = BinaryProtocol.encode(ledgerConfiguration, LedgerSetting.class);
- LedgerSetting deLedgerConfiguration = BinaryProtocol.decode(encodeBytes);
+ byte[] encodeBytes = BinaryProtocol.encode(ledgerConfiguration, LedgerSettings.class);
+ LedgerSettings deLedgerConfiguration = BinaryProtocol.decode(encodeBytes);
// verify start
assertTrue(ledgerConfiguration.getConsensusSetting().equals(deLedgerConfiguration.getConsensusSetting()));
assertEquals(ledgerConfiguration.getCryptoSetting().getAutoVerifyHash(),
@@ -185,8 +185,8 @@ public class LedgerMetaDataTest {
String name = "John";
// NetworkAddress consensusAddress = new NetworkAddress("192.168.1.1", 9001,
// false);
- String address = AddressEncoding.generateAddress(pubKey).toBase58();
- ParticipantCertData participantCertData = new ParticipantCertData(address, name, pubKey);
+ Bytes address = AddressEncoding.generateAddress(pubKey);
+ ParticipantCertData participantCertData = new ParticipantCertData(address, name, pubKey, ParticipantNodeState.ACTIVED);
// encode and decode
byte[] encodeBytes = BinaryProtocol.encode(participantCertData, ParticipantNode.class);
diff --git a/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/LedgerSecurityManagerTest.java b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/LedgerSecurityManagerTest.java
new file mode 100644
index 00000000..7c82d21b
--- /dev/null
+++ b/source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/LedgerSecurityManagerTest.java
@@ -0,0 +1,181 @@
+package test.com.jd.blockchain.ledger.core;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.Test;
+import org.mockito.Mockito;
+
+import com.jd.blockchain.crypto.Crypto;
+import com.jd.blockchain.crypto.CryptoAlgorithm;
+import com.jd.blockchain.crypto.CryptoProvider;
+import com.jd.blockchain.crypto.service.classic.ClassicCryptoService;
+import com.jd.blockchain.crypto.service.sm.SMCryptoService;
+import com.jd.blockchain.ledger.BlockchainKeyGenerator;
+import com.jd.blockchain.ledger.BlockchainKeypair;
+import com.jd.blockchain.ledger.CryptoSetting;
+import com.jd.blockchain.ledger.LedgerPermission;
+import com.jd.blockchain.ledger.ParticipantDataQuery;
+import com.jd.blockchain.ledger.Privileges;
+import com.jd.blockchain.ledger.RolesPolicy;
+import com.jd.blockchain.ledger.TransactionPermission;
+import com.jd.blockchain.ledger.core.CryptoConfig;
+import com.jd.blockchain.ledger.core.LedgerSecurityManager;
+import com.jd.blockchain.ledger.core.LedgerSecurityManagerImpl;
+import com.jd.blockchain.ledger.core.MultiIDsPolicy;
+import com.jd.blockchain.ledger.core.RolePrivilegeDataset;
+import com.jd.blockchain.ledger.core.SecurityPolicy;
+import com.jd.blockchain.ledger.core.UserAccountQuery;
+import com.jd.blockchain.ledger.core.UserRoleDataset;
+import com.jd.blockchain.storage.service.utils.MemoryKVStorage;
+import com.jd.blockchain.utils.Bytes;
+
+public class LedgerSecurityManagerTest {
+
+ private static final String[] SUPPORTED_PROVIDER_NAMES = { ClassicCryptoService.class.getName(),
+ SMCryptoService.class.getName() };
+
+ private static final CryptoAlgorithm HASH_ALGORITHM = Crypto.getAlgorithm("SHA256");
+
+ private static final CryptoProvider[] SUPPORTED_PROVIDERS = new CryptoProvider[SUPPORTED_PROVIDER_NAMES.length];
+
+ private static final CryptoSetting CRYPTO_SETTINGS;
+
+ static {
+ for (int i = 0; i < SUPPORTED_PROVIDER_NAMES.length; i++) {
+ SUPPORTED_PROVIDERS[i] = Crypto.getProvider(SUPPORTED_PROVIDER_NAMES[i]);
+ }
+
+ CryptoConfig cryptoConfig = new CryptoConfig();
+ cryptoConfig.setAutoVerifyHash(true);
+ cryptoConfig.setSupportedProviders(SUPPORTED_PROVIDERS);
+ cryptoConfig.setHashAlgorithm(HASH_ALGORITHM);
+
+ CRYPTO_SETTINGS = cryptoConfig;
+ }
+
+ private RolePrivilegeDataset createRolePrivilegeDataset(MemoryKVStorage testStorage) {
+ String prefix = "role-privilege/";
+ RolePrivilegeDataset rolePrivilegeDataset = new RolePrivilegeDataset(CRYPTO_SETTINGS, prefix, testStorage,
+ testStorage);
+
+ return rolePrivilegeDataset;
+ }
+
+ private UserRoleDataset createUserRoleDataset(MemoryKVStorage testStorage) {
+ String prefix = "user-roles/";
+ UserRoleDataset userRolesDataset = new UserRoleDataset(CRYPTO_SETTINGS, prefix, testStorage, testStorage);
+
+ return userRolesDataset;
+ }
+
+ @Test
+ public void testGetSecurityPolicy() {
+ MemoryKVStorage testStorage = new MemoryKVStorage();
+
+ // 定义不同角色用户的 keypair;
+ final BlockchainKeypair kpManager = BlockchainKeyGenerator.getInstance().generate();
+ final BlockchainKeypair kpEmployee = BlockchainKeyGenerator.getInstance().generate();
+ final BlockchainKeypair kpDevoice = BlockchainKeyGenerator.getInstance().generate();
+ final BlockchainKeypair kpPlatform = BlockchainKeyGenerator.getInstance().generate();
+
+ // 定义角色和权限;
+ final String ROLE_ADMIN = "ID_ADMIN";
+ final String ROLE_OPERATOR = "OPERATOR";
+ final String ROLE_DATA_COLLECTOR = "DATA_COLLECTOR";
+ final String ROLE_PLATFORM = "PLATFORM";
+
+ // 定义管理员角色的权限:【账本权限只允许:注册用户、注册数据账户】【交易权限只允许:调用账本直接操作】
+ final Privileges PRIVILEGES_ADMIN = Privileges.configure()
+ .enable(LedgerPermission.REGISTER_USER, LedgerPermission.REGISTER_DATA_ACCOUNT)
+ .enable(TransactionPermission.DIRECT_OPERATION);
+
+ // 定义操作员角色的权限:【账本权限只允许:写入数据账户】【交易权限只允许:调用合约】
+ final Privileges PRIVILEGES_OPERATOR = Privileges.configure().enable(LedgerPermission.WRITE_DATA_ACCOUNT)
+ .enable(TransactionPermission.CONTRACT_OPERATION);
+
+ // 定义数据收集器角色的权限:【账本权限只允许:写入数据账户】【交易权限只允许:调用账本直接操作】
+ final Privileges PRIVILEGES_DATA_COLLECTOR = Privileges.configure().enable(LedgerPermission.WRITE_DATA_ACCOUNT)
+ .enable(TransactionPermission.DIRECT_OPERATION);
+
+ // 定义平台角色的权限:【账本权限只允许:签署合约】 (只允许作为节点签署交易,不允许作为终端发起交易指令)
+ final Privileges PRIVILEGES_PLATFORM = Privileges.configure().enable(LedgerPermission.APPROVE_TX);
+
+ RolePrivilegeDataset rolePrivilegeDataset = createRolePrivilegeDataset(testStorage);
+ long v = rolePrivilegeDataset.addRolePrivilege(ROLE_ADMIN, PRIVILEGES_ADMIN);
+ assertTrue(v > -1);
+ v = rolePrivilegeDataset.addRolePrivilege(ROLE_OPERATOR, PRIVILEGES_OPERATOR);
+ assertTrue(v > -1);
+ v = rolePrivilegeDataset.addRolePrivilege(ROLE_DATA_COLLECTOR, PRIVILEGES_DATA_COLLECTOR);
+ assertTrue(v > -1);
+ v = rolePrivilegeDataset.addRolePrivilege(ROLE_PLATFORM, PRIVILEGES_PLATFORM);
+ assertTrue(v > -1);
+ rolePrivilegeDataset.commit();
+
+ // 为用户分配角色;
+ String[] managerRoles = new String[] { ROLE_ADMIN, ROLE_OPERATOR };
+ String[] employeeRoles = new String[] { ROLE_OPERATOR };
+ String[] devoiceRoles = new String[] { ROLE_DATA_COLLECTOR };
+ String[] platformRoles = new String[] { ROLE_PLATFORM };
+ UserRoleDataset userRolesDataset = createUserRoleDataset(testStorage);
+ userRolesDataset.addUserRoles(kpManager.getAddress(), RolesPolicy.UNION, managerRoles);
+ userRolesDataset.addUserRoles(kpEmployee.getAddress(), RolesPolicy.UNION, employeeRoles);
+ userRolesDataset.addUserRoles(kpDevoice.getAddress(), RolesPolicy.UNION, devoiceRoles);
+ userRolesDataset.addUserRoles(kpPlatform.getAddress(), RolesPolicy.UNION, platformRoles);
+ userRolesDataset.commit();
+
+ ParticipantDataQuery partisQuery = Mockito.mock(ParticipantDataQuery.class);
+ UserAccountQuery usersQuery = Mockito.mock(UserAccountQuery.class);
+
+ // 创建安全管理器;
+ LedgerSecurityManager securityManager = new LedgerSecurityManagerImpl(rolePrivilegeDataset, userRolesDataset,
+ partisQuery, usersQuery);
+
+ // 定义终端用户列表;终端用户一起共同具有 ADMIN、OPERATOR 角色;
+ final Map
+ * 只对交易请求的节点签名列表{@link TransactionRequest#getNodeSignatures()}的用户产生影响;
+ */
+ APPROVE_TX((byte) 0x0B),
+
+ /**
+ * 参与方共识交易;
+ *
+ * 如果不具备此项权限,则无法作为共识节点接入并对交易进行共识;
+ */
+ CONSENSUS_TX((byte) 0x0C);
+
+ @EnumField(type = PrimitiveType.INT8)
+ public final byte CODE;
+
+ private LedgerPermission(byte code) {
+ this.CODE = code;
+ }
+
+ @Override
+ public byte getCode() {
+ return CODE;
+ }
+
+}
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/LedgerPrivilege.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/LedgerPrivilege.java
new file mode 100644
index 00000000..01261cc2
--- /dev/null
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/LedgerPrivilege.java
@@ -0,0 +1,23 @@
+package com.jd.blockchain.ledger;
+
+/**
+ * LedgerPrivilege 账本特权是授权给特定角色的权限代码序列;
+ *
+ * @author huanghaiquan
+ *
+ */
+public class LedgerPrivilege extends PrivilegeBitset
+ * 如果不存在,则返回 null;
+ *
+ * @param address
+ * @return
+ */
+ ParticipantNode getParticipant(Bytes address);
+
+ ParticipantNode[] getParticipants();
+
+}
\ No newline at end of file
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ParticipantDoesNotExistException.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ParticipantDoesNotExistException.java
new file mode 100644
index 00000000..54994dc7
--- /dev/null
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ParticipantDoesNotExistException.java
@@ -0,0 +1,15 @@
+package com.jd.blockchain.ledger;
+
+public class ParticipantDoesNotExistException extends LedgerException {
+
+ private static final long serialVersionUID = 397450363050148898L;
+
+ public ParticipantDoesNotExistException(String message) {
+ super(message);
+ }
+
+ public ParticipantDoesNotExistException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+}
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ParticipantInfo.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ParticipantInfo.java
index 903cabfd..c366fdd3 100644
--- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ParticipantInfo.java
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ParticipantInfo.java
@@ -1,35 +1,52 @@
-//package com.jd.blockchain.ledger;
-//
-//import com.jd.blockchain.base.data.TypeCodes;
-//import com.jd.blockchain.binaryproto.DataContract;
-//import com.jd.blockchain.binaryproto.DataField;
-//import com.jd.blockchain.crypto.asymmetric.PubKey;
-//
-//import my.utils.ValueType;
-//
-///**
-// * 参与方信息;
-// *
-// * @author huanghaiquan
-// *
-// */
-//@DataContract(code = TypeCodes.METADATA_PARTICIPANT_INFO)
-//public interface ParticipantInfo {
-//
-// /**
-// * 参与者名称;
-// *
-// * @return
-// */
-// @DataField(order = 1, primitiveType = ValueType.TEXT)
-// String getName();
-//
-// /**
-// * 公钥;
-// *
-// * @return
-// */
-// @DataField(order = 2, primitiveType = ValueType.BYTES)
-// PubKey getPubKey();
-//
-//}
\ No newline at end of file
+package com.jd.blockchain.ledger;
+
+import com.jd.blockchain.binaryproto.DataContract;
+import com.jd.blockchain.binaryproto.DataField;
+import com.jd.blockchain.binaryproto.PrimitiveType;
+import com.jd.blockchain.consts.DataCodes;
+import com.jd.blockchain.crypto.PubKey;
+import com.jd.blockchain.utils.net.NetworkAddress;
+
+
+/**
+ * 参与方信息;
+ *
+ * @author huanghaiquan
+ *
+ */
+@DataContract(code = DataCodes.METADATA_PARTICIPANT_INFO)
+public interface ParticipantInfo {
+
+ /**
+ * regist or unregist, temporarily not available to users
+ *
+ * @return
+ */
+// @DataField(order = 0, primitiveType = PrimitiveType.TEXT)
+// String getFlag();
+
+ /**
+ * 参与者名称;
+ *
+ * @return
+ */
+ @DataField(order = 1, primitiveType = PrimitiveType.TEXT)
+ String getName();
+
+ /**
+ * 公钥;
+ *
+ * @return
+ */
+ @DataField(order = 2, primitiveType = PrimitiveType.BYTES)
+ PubKey getPubKey();
+
+ /**
+ * 共识协议的网络地址;
+ *
+ * @return
+ */
+ @DataField(order = 3, primitiveType = PrimitiveType.BYTES)
+ NetworkAddress getNetworkAddress();
+
+}
\ No newline at end of file
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ParticipantInfoData.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ParticipantInfoData.java
new file mode 100644
index 00000000..27eaa098
--- /dev/null
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ParticipantInfoData.java
@@ -0,0 +1,56 @@
+package com.jd.blockchain.ledger;
+
+import com.jd.blockchain.crypto.PubKey;
+import com.jd.blockchain.utils.net.NetworkAddress;
+import org.omg.CORBA.PUBLIC_MEMBER;
+
+/**
+ * 即将要注册的参与方的信息
+ * @author zhangshuang
+ * @create 2019/7/8
+ * @since 1.0.0
+ */
+public class ParticipantInfoData implements ParticipantInfo {
+
+
+ private String name;
+
+ private PubKey pubKey;
+
+ private NetworkAddress networkAddress;
+
+// private String flag;//代表注册参与方或者删除参与方
+
+ public ParticipantInfoData(String name, PubKey pubKey, NetworkAddress networkAddress) {
+ this.name = name;
+ this.pubKey = pubKey;
+ this.networkAddress = networkAddress;
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ @Override
+ public PubKey getPubKey() {
+ return pubKey;
+ }
+
+ public void setPubKey(PubKey pubKey) {
+ this.pubKey = pubKey;
+ }
+
+ @Override
+ public NetworkAddress getNetworkAddress() {
+ return networkAddress;
+ }
+
+ public void setNetworkAddress(NetworkAddress networkAddress) {
+ this.networkAddress = networkAddress;
+ }
+}
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ParticipantNode.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ParticipantNode.java
index dd2c62fa..9be89492 100644
--- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ParticipantNode.java
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ParticipantNode.java
@@ -5,6 +5,7 @@ import com.jd.blockchain.binaryproto.DataField;
import com.jd.blockchain.binaryproto.PrimitiveType;
import com.jd.blockchain.consts.DataCodes;
import com.jd.blockchain.crypto.PubKey;
+import com.jd.blockchain.utils.Bytes;
/**
* 参与方节点;
@@ -13,7 +14,7 @@ import com.jd.blockchain.crypto.PubKey;
*
*/
@DataContract(code = DataCodes.METADATA_CONSENSUS_PARTICIPANT)
-public interface ParticipantNode {// extends ConsensusNode, ParticipantInfo {
+public interface ParticipantNode {
/**
* 节点的顺序编号;
@@ -30,8 +31,8 @@ public interface ParticipantNode {// extends ConsensusNode, ParticipantInfo {
*
* @return
*/
- @DataField(order = 1, primitiveType = PrimitiveType.TEXT)
- String getAddress();
+ @DataField(order = 1, primitiveType = PrimitiveType.BYTES)
+ Bytes getAddress();
/**
* 参与者名称;
@@ -48,4 +49,12 @@ public interface ParticipantNode {// extends ConsensusNode, ParticipantInfo {
*/
@DataField(order = 3, primitiveType = PrimitiveType.BYTES)
PubKey getPubKey();
+
+ /**
+ * 节点的状态:已注册/已参与共识
+ *
+ * @return
+ */
+ @DataField(order = 4, refEnum = true)
+ ParticipantNodeState getParticipantNodeState();
}
\ No newline at end of file
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ParticipantNodeState.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ParticipantNodeState.java
new file mode 100644
index 00000000..f7b97fd1
--- /dev/null
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ParticipantNodeState.java
@@ -0,0 +1,43 @@
+package com.jd.blockchain.ledger;
+
+import com.jd.blockchain.binaryproto.EnumContract;
+import com.jd.blockchain.binaryproto.EnumField;
+import com.jd.blockchain.binaryproto.PrimitiveType;
+import com.jd.blockchain.consts.DataCodes;
+
+
+/**
+ * 参与方节点状态
+ * @author zhangshuang
+ * @create 2019/7/8
+ * @since 1.0.0
+ */
+@EnumContract(code= DataCodes.ENUM_TYPE_PARTICIPANT_NODE_STATE)
+public enum ParticipantNodeState {
+
+ /**
+ * 已注册;
+ */
+ REGISTERED((byte) 0),
+
+ /**
+ * 已激活;
+ */
+ ACTIVED((byte) 1);
+
+ @EnumField(type= PrimitiveType.INT8)
+ public final byte CODE;
+
+ private ParticipantNodeState(byte code) {
+ this.CODE = code;
+ }
+
+ public static ParticipantNodeState valueOf(byte code) {
+ for (ParticipantNodeState tr : values()) {
+ if (tr.CODE == code) {
+ return tr;
+ }
+ }
+ throw new IllegalArgumentException("Unsupported participant node state code!");
+ }
+}
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ParticipantRegisterOperation.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ParticipantRegisterOperation.java
new file mode 100644
index 00000000..ec946593
--- /dev/null
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ParticipantRegisterOperation.java
@@ -0,0 +1,20 @@
+package com.jd.blockchain.ledger;
+
+import com.jd.blockchain.binaryproto.DataContract;
+import com.jd.blockchain.binaryproto.DataField;
+import com.jd.blockchain.binaryproto.PrimitiveType;
+import com.jd.blockchain.consts.DataCodes;
+import com.jd.blockchain.utils.net.NetworkAddress;
+
+@DataContract(code= DataCodes.TX_OP_PARTICIPANT_REG)
+public interface ParticipantRegisterOperation extends Operation {
+
+ @DataField(order = 0, primitiveType=PrimitiveType.TEXT)
+ String getParticipantName();
+
+ @DataField(order = 1, refContract = true)
+ BlockchainIdentity getParticipantRegisterIdentity();
+
+ @DataField(order = 2, primitiveType = PrimitiveType.BYTES)
+ NetworkAddress getNetworkAddress();
+}
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ParticipantStateUpdateInfo.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ParticipantStateUpdateInfo.java
new file mode 100644
index 00000000..70c89f3f
--- /dev/null
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ParticipantStateUpdateInfo.java
@@ -0,0 +1,41 @@
+package com.jd.blockchain.ledger;
+
+import com.jd.blockchain.binaryproto.DataContract;
+import com.jd.blockchain.binaryproto.DataField;
+import com.jd.blockchain.binaryproto.PrimitiveType;
+import com.jd.blockchain.consts.DataCodes;
+import com.jd.blockchain.crypto.PubKey;
+import com.jd.blockchain.utils.net.NetworkAddress;
+
+/**
+ * 参与方状态更新信息;
+ *
+ *
+ */
+@DataContract(code = DataCodes.METADATA_PARTICIPANT_STATE_INFO)
+public interface ParticipantStateUpdateInfo {
+
+ /**
+ * 公钥;
+ *
+ * @return
+ */
+ @DataField(order = 1, primitiveType = PrimitiveType.BYTES)
+ PubKey getPubKey();
+
+ /**
+ * 共识协议的网络地址;
+ *
+ * @return
+ */
+ @DataField(order = 2, primitiveType = PrimitiveType.BYTES)
+ NetworkAddress getNetworkAddress();
+
+ /**
+ * 参与方状态;
+ *
+ * @return
+ */
+ @DataField(order = 3, refEnum = true)
+ ParticipantNodeState getState();
+}
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ParticipantStateUpdateInfoData.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ParticipantStateUpdateInfoData.java
new file mode 100644
index 00000000..5e11c178
--- /dev/null
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ParticipantStateUpdateInfoData.java
@@ -0,0 +1,43 @@
+package com.jd.blockchain.ledger;
+
+import com.jd.blockchain.crypto.PubKey;
+import com.jd.blockchain.utils.net.NetworkAddress;
+
+public class ParticipantStateUpdateInfoData implements ParticipantStateUpdateInfo {
+ private PubKey pubKey;
+ private ParticipantNodeState state;
+ private NetworkAddress networkAddress;
+
+ public ParticipantStateUpdateInfoData(PubKey pubKey, ParticipantNodeState state, NetworkAddress networkAddress) {
+ this.pubKey = pubKey;
+ this.state = state;
+ this.networkAddress = networkAddress;
+ }
+
+ public void setPubKey(PubKey pubKey) {
+ this.pubKey = pubKey;
+ }
+
+ @Override
+ public PubKey getPubKey() {
+ return pubKey;
+ }
+
+ public void setNetworkAddress(NetworkAddress networkAddress) {
+ this.networkAddress = networkAddress;
+ }
+
+ @Override
+ public NetworkAddress getNetworkAddress() {
+ return networkAddress;
+ }
+
+ public void setState(ParticipantNodeState state) {
+ this.state = state;
+ }
+
+ @Override
+ public ParticipantNodeState getState() {
+ return state;
+ }
+}
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ParticipantStateUpdateOperation.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ParticipantStateUpdateOperation.java
new file mode 100644
index 00000000..fa2791a7
--- /dev/null
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ParticipantStateUpdateOperation.java
@@ -0,0 +1,21 @@
+package com.jd.blockchain.ledger;
+
+import com.jd.blockchain.binaryproto.DataContract;
+import com.jd.blockchain.binaryproto.DataField;
+import com.jd.blockchain.binaryproto.PrimitiveType;
+import com.jd.blockchain.consts.DataCodes;
+import com.jd.blockchain.utils.net.NetworkAddress;
+
+@DataContract(code= DataCodes.TX_OP_PARTICIPANT_STATE_UPDATE)
+public interface ParticipantStateUpdateOperation extends Operation {
+
+ @DataField(order = 0, refContract = true)
+ BlockchainIdentity getStateUpdateIdentity();
+
+ @DataField(order = 1, primitiveType = PrimitiveType.BYTES)
+ NetworkAddress getNetworkAddress();
+
+ @DataField(order = 2, refEnum = true)
+ ParticipantNodeState getState();
+
+}
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/Privilege.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/Privilege.java
new file mode 100644
index 00000000..4a77e0b9
--- /dev/null
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/Privilege.java
@@ -0,0 +1,5 @@
+package com.jd.blockchain.ledger;
+
+public interface Privilege
+ *
+ * @param privileges
+ * @return
+ */
+ @SuppressWarnings("unchecked")
+ public Privilege
+ *
+ * @param privileges
+ * @param offset
+ * @param count
+ * @return
+ */
+ public Privilege
+ *
+ * @param privileges
+ * @return
+ */
+ @SuppressWarnings("unchecked")
+ public Privilege
+ *
+ * @param privileges
+ * @param offset
+ * @param count
+ * @return
+ */
+ public Privilege
+ * 如果不存在,则返回 null;
+ *
+ * @param address
+ * @return
+ */
+ RolePrivileges getRolePrivilege(String roleName);
+
+ /**
+ * 返回指定位置的角色权限;
+ *
+ * @param index
+ * @param count
+ * @return
+ */
+ RolePrivileges[] getRolePrivileges(int index, int count);
+
+ /**
+ * 返回所有的角色权限;
+ *
+ * @return
+ */
+ RolePrivileges[] getRolePrivileges();
+
+ /**
+ * 是否只读;
+ *
+ * @return
+ */
+ boolean isReadonly();
+
+ /**
+ * 加入新的角色权限;
+ *
+ * 如果指定的角色已经存在,则引发 {@link LedgerException} 异常;
+ *
+ * @param roleName 角色名称;不能超过 {@link #MAX_ROLE_NAME_LENGTH} 个 Unicode 字符;
+ * @param ledgerPrivilege
+ * @param txPrivilege
+ */
+ long addRolePrivilege(String roleName, Privileges privileges);
+
+ /**
+ * 加入新的角色权限;
+ *
+ * 如果指定的角色已经存在,则引发 {@link LedgerException} 异常;
+ *
+ * @param roleName 角色名称;不能超过 {@link #MAX_ROLE_NAME_LENGTH} 个 Unicode 字符;
+ * @param ledgerPrivilege
+ * @param txPrivilege
+ */
+ long addRolePrivilege(String roleName, LedgerPrivilege ledgerPrivilege, TransactionPrivilege txPrivilege);
+
+ /**
+ * 加入新的角色权限;
+ *
+ * 如果指定的角色已经存在,则引发 {@link LedgerException} 异常;
+ *
+ * @param roleName 角色名称;不能超过 {@link #MAX_ROLE_NAME_LENGTH} 个 Unicode
+ * 字符;
+ * @param ledgerPermissions 给角色授予的账本权限列表;
+ * @param txPermissions 给角色授予的交易权限列表;
+ * @return
+ */
+ long addRolePrivilege(String roleName, LedgerPermission[] ledgerPermissions, TransactionPermission[] txPermissions);
+
+ /**
+ * 更新角色权限;
+ * 如果指定的角色不存在,或者版本不匹配,则引发 {@link LedgerException} 异常;
+ *
+ * @param participant
+ */
+ void updateRolePrivilege(RolePrivileges roleAuth);
+
+ /**
+ * 授权角色指定的权限;
+ * 如果角色不存在,则返回 -1;
+ *
+ * @param roleName 角色;
+ * @param permissions 权限列表;
+ * @return
+ */
+ long enablePermissions(String roleName, LedgerPermission... permissions);
+
+ /**
+ * 授权角色指定的权限;
+ * 如果角色不存在,则返回 -1;
+ *
+ * @param roleName 角色;
+ * @param permissions 权限列表;
+ * @return
+ */
+ long enablePermissions(String roleName, TransactionPermission... permissions);
+
+ /**
+ * 禁止角色指定的权限;
+ * 如果角色不存在,则返回 -1;
+ *
+ * @param roleName 角色;
+ * @param permissions 权限列表;
+ * @return
+ */
+ long disablePermissions(String roleName, LedgerPermission... permissions);
+
+ /**
+ * 禁止角色指定的权限;
+ * 如果角色不存在,则返回 -1;
+ *
+ * @param roleName 角色;
+ * @param permissions 权限列表;
+ * @return
+ */
+ long disablePermissions(String roleName, TransactionPermission... permissions);
+
+ /**
+ * 授权角色指定的权限;
+ * 如果角色不存在,则返回 -1;
+ *
+ * @param roleName
+ * @param ledgerPermissions
+ * @param txPermissions
+ * @return
+ */
+ long enablePermissions(String roleName, LedgerPermission[] ledgerPermissions,
+ TransactionPermission[] txPermissions);
+
+ /**
+ * 禁用角色指定的权限;
+ * 如果角色不存在,则返回 -1;
+ *
+ * @param roleName
+ * @param ledgerPermissions
+ * @param txPermissions
+ * @return
+ */
+ long disablePermissions(String roleName, LedgerPermission[] ledgerPermissions,
+ TransactionPermission[] txPermissions);
+
+ boolean contains(String r);
+
+}
\ No newline at end of file
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/RolePrivileges.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/RolePrivileges.java
new file mode 100644
index 00000000..1b0b32ba
--- /dev/null
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/RolePrivileges.java
@@ -0,0 +1,41 @@
+package com.jd.blockchain.ledger;
+
+/**
+ * 对角色的授权;
+ *
+ * @author huanghaiquan
+ *
+ */
+public class RolePrivileges extends Privileges {
+
+ private String roleName;
+
+ private long version;
+
+ public RolePrivileges(String roleName, long version) {
+ this.roleName = roleName;
+ this.version = version;
+ }
+
+ public RolePrivileges(String roleName, long version, PrivilegeSet privilege) {
+ super(privilege);
+ this.roleName = roleName;
+ this.version = version;
+ }
+
+ public RolePrivileges(String roleName, long version, LedgerPrivilege ledgerPrivilege,
+ TransactionPrivilege txPrivilege) {
+ super(ledgerPrivilege, txPrivilege);
+ this.roleName = roleName;
+ this.version = version;
+ }
+
+ public String getRoleName() {
+ return roleName;
+ }
+
+ public long getVersion() {
+ return version;
+ }
+
+}
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/RoleSet.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/RoleSet.java
new file mode 100644
index 00000000..a026c23f
--- /dev/null
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/RoleSet.java
@@ -0,0 +1,23 @@
+package com.jd.blockchain.ledger;
+
+import com.jd.blockchain.binaryproto.DataContract;
+import com.jd.blockchain.binaryproto.DataField;
+import com.jd.blockchain.binaryproto.PrimitiveType;
+import com.jd.blockchain.consts.DataCodes;
+
+/**
+ * 角色集;
+ *
+ * @author huanghaiquan
+ *
+ */
+@DataContract(code = DataCodes.ROLE_SET)
+public interface RoleSet {
+
+ @DataField(order = 1, refEnum = true)
+ RolesPolicy getPolicy();
+
+ @DataField(order = 2, primitiveType = PrimitiveType.TEXT, list = true)
+ String[] getRoles();
+
+}
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/RolesConfigureOperation.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/RolesConfigureOperation.java
new file mode 100644
index 00000000..1e448740
--- /dev/null
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/RolesConfigureOperation.java
@@ -0,0 +1,39 @@
+package com.jd.blockchain.ledger;
+
+import com.jd.blockchain.binaryproto.DataContract;
+import com.jd.blockchain.binaryproto.DataField;
+import com.jd.blockchain.binaryproto.PrimitiveType;
+import com.jd.blockchain.consts.DataCodes;
+
+/**
+ * 角色配置操作;
+ *
+ * @author huanghaiquan
+ *
+ */
+@DataContract(code = DataCodes.TX_OP_ROLE_CONFIGURE)
+public interface RolesConfigureOperation extends Operation {
+
+ @DataField(order = 2, refContract = true, list = true)
+ RolePrivilegeEntry[] getRoles();
+
+ @DataContract(code = DataCodes.TX_OP_ROLE_CONFIGURE_ENTRY)
+ public static interface RolePrivilegeEntry {
+
+ @DataField(order = 1, primitiveType = PrimitiveType.TEXT)
+ String getRoleName();
+
+ @DataField(order = 2, refEnum = true, list = true)
+ LedgerPermission[] getEnableLedgerPermissions();
+
+ @DataField(order = 3, refEnum = true, list = true)
+ LedgerPermission[] getDisableLedgerPermissions();
+
+ @DataField(order = 4, refEnum = true, list = true)
+ TransactionPermission[] getEnableTransactionPermissions();
+
+ @DataField(order = 5, refEnum = true, list = true)
+ TransactionPermission[] getDisableTransactionPermissions();
+
+ }
+}
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/RolesPolicy.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/RolesPolicy.java
new file mode 100644
index 00000000..690d0be5
--- /dev/null
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/RolesPolicy.java
@@ -0,0 +1,40 @@
+package com.jd.blockchain.ledger;
+
+import com.jd.blockchain.binaryproto.EnumContract;
+import com.jd.blockchain.binaryproto.EnumField;
+import com.jd.blockchain.binaryproto.PrimitiveType;
+import com.jd.blockchain.consts.DataCodes;
+
+/**
+ * 多角色策略;
+ *
+ * 表示如何处理一个对象被赋予多个角色时的综合权限;
+ *
+ * @author huanghaiquan
+ *
+ */
+@EnumContract(code = DataCodes.ENUM_MULTI_ROLES_POLICY, name = "USER-ROLE-POLICY")
+public enum RolesPolicy {
+
+ /**
+ * 合并权限;
+ *
+ * 综合权限是所有角色权限的并集,即任何一个角色的权限都被继承;
+ */
+ UNION((byte) 0),
+
+ /**
+ * 交叉权限;
+ *
+ * 综合权限是所有角色权限的交集,即只有全部角色共同拥有的权限才会被继承;
+ */
+ INTERSECT((byte) 1);
+
+ @EnumField(type = PrimitiveType.INT8)
+ public final byte CODE;
+
+ private RolesPolicy(byte code) {
+ this.CODE = code;
+ }
+
+}
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/SecurityInitData.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/SecurityInitData.java
new file mode 100644
index 00000000..90f51869
--- /dev/null
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/SecurityInitData.java
@@ -0,0 +1,60 @@
+package com.jd.blockchain.ledger;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import com.jd.blockchain.binaryproto.DataContractRegistry;
+import com.jd.blockchain.utils.Bytes;
+
+public class SecurityInitData implements SecurityInitSettings {
+
+ static {
+ DataContractRegistry.register(SecurityInitSettings.class);
+ }
+
+
+ private Map
+ * 如果不存在,则返回 null;
+ *
+ * @param address
+ * @return
+ */
+ UserRoles getUserRoles(Bytes userAddress);
+
+ /**
+ * 返回全部的用户授权;
+ *
+ * @return
+ */
+ UserRoles[] getUserRoles();
+
+ /**
+ * 是否只读;
+ *
+ * @return
+ */
+ boolean isReadonly();
+
+ /**
+ * 加入新的用户角色授权;
+ *
+ * 如果该用户的授权已经存在,则引发 {@link LedgerException} 异常;
+ *
+ * @param userAddress
+ * @param rolesPolicy
+ * @param roles
+ */
+ void addUserRoles(Bytes userAddress, RolesPolicy rolesPolicy, String... roles);
+
+ /**
+ * 加入新的用户角色授权;
+ *
+ * 如果该用户的授权已经存在,则引发 {@link LedgerException} 异常;
+ *
+ * @param userAddress
+ * @param rolesPolicy
+ * @param roles
+ */
+ void addUserRoles(Bytes userAddress, RolesPolicy rolesPolicy, Collection
+ * 如果指定用户的授权不存在,或者版本不匹配,则引发 {@link LedgerException} 异常;
+ *
+ * @param userRoles
+ */
+ void updateUserRoles(UserRoles userRoles);
+
+ /**
+ * 设置用户的角色;
+ * 如果用户的角色授权不存在,则创建新的授权;
+ *
+ * @param userAddress 用户;
+ * @param policy 角色策略;
+ * @param roles 角色列表;
+ * @return
+ */
+ long setRoles(Bytes userAddress, RolesPolicy policy, String... roles);
+
+}
\ No newline at end of file
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/UserAuthorizeOperation.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/UserAuthorizeOperation.java
new file mode 100644
index 00000000..67e37e17
--- /dev/null
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/UserAuthorizeOperation.java
@@ -0,0 +1,57 @@
+package com.jd.blockchain.ledger;
+
+import com.jd.blockchain.binaryproto.DataContract;
+import com.jd.blockchain.binaryproto.DataField;
+import com.jd.blockchain.binaryproto.PrimitiveType;
+import com.jd.blockchain.consts.DataCodes;
+import com.jd.blockchain.utils.Bytes;
+
+/**
+ * 角色配置操作;
+ *
+ * @author huanghaiquan
+ *
+ */
+@DataContract(code = DataCodes.TX_OP_USER_ROLES_AUTHORIZE)
+public interface UserAuthorizeOperation extends Operation {
+
+ @DataField(order = 2, refContract = true, list = true)
+ UserRolesEntry[] getUserRolesAuthorizations();
+
+ @DataContract(code = DataCodes.TX_OP_USER_ROLE_AUTHORIZE_ENTRY)
+ public static interface UserRolesEntry {
+
+ /**
+ * 用户地址;
+ *
+ * @return
+ */
+ @DataField(order = 0, primitiveType = PrimitiveType.BYTES, list = true)
+ Bytes[] getUserAddresses();
+
+ /**
+ * 要更新的多角色权限策略;
+ *
+ * @return
+ */
+ @DataField(order = 2, refEnum = true)
+ RolesPolicy getPolicy();
+
+ /**
+ * 授权的角色清单;
+ *
+ * @return
+ */
+ @DataField(order = 3, primitiveType = PrimitiveType.TEXT, list = true)
+ String[] getAuthorizedRoles();
+
+ /**
+ * 取消授权的角色清单;
+ *
+ * @return
+ */
+ @DataField(order = 4, primitiveType = PrimitiveType.TEXT, list = true)
+ String[] getUnauthorizedRoles();
+
+ }
+}
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/UserInfoSetOperation.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/UserInfoSetOperation.java
index b9a92317..c6372b78 100644
--- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/UserInfoSetOperation.java
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/UserInfoSetOperation.java
@@ -1,33 +1,29 @@
-//package com.jd.blockchain.ledger;
-//
-//import com.jd.blockchain.binaryproto.DataContract;
-//
-///**
-// * @author huanghaiquan
-// *
-// */
-//@DataContract(code=LedgerCodes.TX_OP_USER_INFO_SET)
-//public interface UserInfoSetOperation extends Operation {
-//
-// @Override
-// default OperationType getType() {
-// return OperationType.SET_USER_INFO;
-// }
-//
-// String getUserAddress();
-//
-// KVEntry[] getPropertiesWriteSet();
-//
-//
-// @DataContract(code=LedgerCodes.TX_OP_USER_INFO_SET_KV)
-// public static interface KVEntry{
-//
-// String getKey();
-//
-// String getValue();
-//
-// long getExpectedVersion();
-// }
-//
-//
-//}
+package com.jd.blockchain.ledger;
+
+import com.jd.blockchain.binaryproto.DataContract;
+import com.jd.blockchain.consts.DataCodes;
+
+/**
+ * @author huanghaiquan
+ *
+ */
+@DataContract(code=DataCodes.TX_OP_USER_INFO_SET)
+public interface UserInfoSetOperation extends Operation {
+
+ String getUserAddress();
+
+ KVEntry[] getPropertiesWriteSet();
+
+
+ @DataContract(code=DataCodes.TX_OP_USER_INFO_SET_KV)
+ public static interface KVEntry{
+
+ String getKey();
+
+ String getValue();
+
+ long getExpectedVersion();
+ }
+
+
+}
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/UserRegisterOperation.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/UserRegisterOperation.java
index f325085e..caa642de 100644
--- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/UserRegisterOperation.java
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/UserRegisterOperation.java
@@ -4,10 +4,10 @@ import com.jd.blockchain.binaryproto.DataContract;
import com.jd.blockchain.binaryproto.DataField;
import com.jd.blockchain.consts.DataCodes;
-@DataContract(code= DataCodes.TX_OP_USER_REG)
+@DataContract(code = DataCodes.TX_OP_USER_REG)
public interface UserRegisterOperation extends Operation {
-
- @DataField(order=2, refContract = true)
- BlockchainIdentity getUserID();
+ @DataField(order = 2, refContract = true)
+ BlockchainIdentity getUserID();
+
}
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/UserRoles.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/UserRoles.java
new file mode 100644
index 00000000..19f86ed8
--- /dev/null
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/UserRoles.java
@@ -0,0 +1,117 @@
+package com.jd.blockchain.ledger;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Set;
+import java.util.TreeSet;
+
+import com.jd.blockchain.binaryproto.DataContractRegistry;
+import com.jd.blockchain.utils.Bytes;
+
+public class UserRoles implements RoleSet {
+
+ static {
+ DataContractRegistry.register(RoleSet.class);
+ }
+
+ private Bytes userAddress;
+
+ private RolesPolicy policy;
+
+ private Set
+ * 注意,这不是追加;现有的不在参数指定范围的角色将被移除;
+ *
+ * @param roles
+ */
+ public void setRoles(String[] roles) {
+ TreeSet
- * 最小为1,最大值受到系统参数的限制;
- * 注:通过 {@link #getBlock(String, long)} 方法获得的区块信息中可以得到区块的总交易数
- * {@link Block#getTxCount()};
* @return
*/
- LedgerTransaction[] getTransactions(HashDigest ledgerHash, long height, int fromIndex, int count);
+ long getContractCount(HashDigest ledgerHash, long height);
/**
- * 分页返回指定账本序号的区块中的交易列表;
+ * 返回指定区块中的合约总数
*
* @param ledgerHash
- * 账本hash;
* @param blockHash
- * 账本高度;
- * @param fromIndex
- * 开始的记录数;
- * @param count
- * 本次返回的记录数;
- * 如果参数值为 -1,则返回全部的记录;
- * 注:通过 {@link #getBlock(String, String)} 方法获得的区块信息中可以得到区块的总交易数
- * {@link Block#getTxCount()};
+ * @return
+ */
+ long getContractCount(HashDigest ledgerHash, HashDigest blockHash);
+
+ /**
+ * 返回当前账本的合约总数
+ *
+ * @param ledgerHash
+ * @return
+ */
+ long getContractTotalCount(HashDigest ledgerHash);
+
+ /**
+ * 分页返回指定账本序号的区块中的交易列表;
+ *
+ * @param ledgerHash 账本hash;
+ * @param height 账本高度;
+ * @param fromIndex 开始的记录数;
+ * @param count 本次返回的记录数;
+ * 最小为1,最大值受到系统参数的限制;
+ * 注:通过 {@link #getBlock(String, long)} 方法获得的区块信息中可以得到区块的总交易数
+ * {@link Block#getTxCount()};
+ * @return
+ */
+ LedgerTransaction[] getTransactions(HashDigest ledgerHash, long height, int fromIndex, int count);
+
+ /**
+ * 分页返回指定账本序号的区块中的交易列表;
+ *
+ * @param ledgerHash 账本hash;
+ * @param blockHash 账本高度;
+ * @param fromIndex 开始的记录数;
+ * @param count 本次返回的记录数;
+ * 如果参数值为 -1,则返回全部的记录;
+ * 注:通过 {@link #getBlock(String, String)}
+ * 方法获得的区块信息中可以得到区块的总交易数 {@link Block#getTxCount()};
* @return
*/
LedgerTransaction[] getTransactions(HashDigest ledgerHash, HashDigest blockHash, int fromIndex, int count);
@@ -210,21 +219,17 @@ public interface BlockchainQueryService {
/**
* 根据交易内容的哈希获取对应的交易记录;
*
- * @param ledgerHash
- * 账本hash;
- * @param contentHash
- * 交易内容的hash,即交易的 {@link Transaction#getContentHash()} 属性的值;
+ * @param ledgerHash 账本hash;
+ * @param contentHash 交易内容的hash,即交易的 {@link Transaction#getContentHash()} 属性的值;
* @return
*/
LedgerTransaction getTransactionByContentHash(HashDigest ledgerHash, HashDigest contentHash);
-
+
/**
* 根据交易内容的哈希获取对应的交易状态;
*
- * @param ledgerHash
- * 账本hash;
- * @param contentHash
- * 交易内容的hash,即交易的 {@link Transaction#getContentHash()} 属性的值;
+ * @param ledgerHash 账本hash;
+ * @param contentHash 交易内容的hash,即交易的 {@link Transaction#getContentHash()} 属性的值;
* @return
*/
TransactionState getTransactionStateByContentHash(HashDigest ledgerHash, HashDigest contentHash);
@@ -273,18 +278,13 @@ public interface BlockchainQueryService {
long getDataEntriesTotalCount(HashDigest ledgerHash, String address);
/**
- * 返回数据账户中指定序号的最新值;
- * 返回结果的顺序与指定的序号的顺序是一致的;
+ * 返回数据账户中指定序号的最新值; 返回结果的顺序与指定的序号的顺序是一致的;
*
- * @param ledgerHash
- * 账本hash;
- * @param address
- * 数据账户地址;
- * @param fromIndex
- * 开始的记录数;
- * @param count
- * 本次返回的记录数;
- * 如果参数值为 -1,则返回全部的记录;
+ * @param ledgerHash 账本hash;
+ * @param address 数据账户地址;
+ * @param fromIndex 开始的记录数;
+ * @param count 本次返回的记录数;
+ * 如果参数值为 -1,则返回全部的记录;
* @return
*/
KVDataEntry[] getDataEntries(HashDigest ledgerHash, String address, int fromIndex, int count);
@@ -300,6 +300,7 @@ public interface BlockchainQueryService {
/**
* get users by ledgerHash and its range;
+ *
* @param ledgerHash
* @param fromIndex
* @param count
@@ -309,6 +310,7 @@ public interface BlockchainQueryService {
/**
* get data accounts by ledgerHash and its range;
+ *
* @param ledgerHash
* @param fromIndex
* @param count
@@ -318,6 +320,7 @@ public interface BlockchainQueryService {
/**
* get contract accounts by ledgerHash and its range;
+ *
* @param ledgerHash
* @param fromIndex
* @param count
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ClientOperator.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ClientOperator.java
index 5e47ef89..cba4569e 100644
--- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ClientOperator.java
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ClientOperator.java
@@ -6,6 +6,7 @@ package com.jd.blockchain.transaction;
* @author huanghaiquan
*
*/
-public interface ClientOperator extends UserOperator, DataAccountOperator, ContractOperator, EventOperator {
+public interface ClientOperator
+ extends SecurityOperator, UserOperator, DataAccountOperator, ContractOperator, EventOperator, ParticipantOperator {
}
\ No newline at end of file
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ConsensusParticipantData.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ConsensusParticipantData.java
index b4e64744..e182ced1 100644
--- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ConsensusParticipantData.java
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ConsensusParticipantData.java
@@ -2,13 +2,15 @@ package com.jd.blockchain.transaction;
import com.jd.blockchain.crypto.PubKey;
import com.jd.blockchain.ledger.ParticipantNode;
+import com.jd.blockchain.utils.Bytes;
import com.jd.blockchain.utils.net.NetworkAddress;
+import com.jd.blockchain.ledger.ParticipantNodeState;
public class ConsensusParticipantData implements ParticipantNode {
private int id;
- private String address;
+ private Bytes address;
private String name;
@@ -16,6 +18,9 @@ public class ConsensusParticipantData implements ParticipantNode {
private NetworkAddress hostAddress;
+ private ParticipantNodeState participantNodeState;
+
+ @Override
public int getId() {
return id;
}
@@ -24,6 +29,7 @@ public class ConsensusParticipantData implements ParticipantNode {
this.id = id;
}
+ @Override
public String getName() {
return name;
}
@@ -32,7 +38,7 @@ public class ConsensusParticipantData implements ParticipantNode {
this.name = name;
}
- public NetworkAddress getConsensusAddress() {
+ public NetworkAddress getHostAddress() {
return hostAddress;
}
@@ -40,6 +46,7 @@ public class ConsensusParticipantData implements ParticipantNode {
this.hostAddress = hostAddress;
}
+ @Override
public PubKey getPubKey() {
return pubKey;
}
@@ -48,12 +55,22 @@ public class ConsensusParticipantData implements ParticipantNode {
this.pubKey = pubKey;
}
- public String getAddress() {
+ @Override
+ public Bytes getAddress() {
return address;
}
- public void setAddress(String address) {
+ public void setAddress(Bytes address) {
this.address = address;
}
+ @Override
+ public ParticipantNodeState getParticipantNodeState() {
+ return participantNodeState;
+ }
+
+ public void setParticipantState(ParticipantNodeState participantNodeState) {
+ this.participantNodeState = participantNodeState;
+ }
+
}
\ No newline at end of file
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/LedgerInitSettingData.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/LedgerInitData.java
similarity index 80%
rename from source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/LedgerInitSettingData.java
rename to source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/LedgerInitData.java
index a6f6045a..656b4aa3 100644
--- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/LedgerInitSettingData.java
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/LedgerInitData.java
@@ -1,22 +1,28 @@
package com.jd.blockchain.transaction;
-import com.jd.blockchain.ledger.ParticipantNode;
-import com.jd.blockchain.utils.Bytes;
+import com.jd.blockchain.binaryproto.DataContractRegistry;
import com.jd.blockchain.ledger.CryptoSetting;
import com.jd.blockchain.ledger.LedgerInitSetting;
+import com.jd.blockchain.ledger.ParticipantNode;
+import com.jd.blockchain.ledger.UserAuthInitSettings;
+import com.jd.blockchain.utils.Bytes;
+
+public class LedgerInitData implements LedgerInitSetting {
-public class LedgerInitSettingData implements LedgerInitSetting {
+ static {
+ DataContractRegistry.register(LedgerInitSetting.class);
+ }
private byte[] ledgerSeed;
private ParticipantNode[] consensusParticipants;
private CryptoSetting cryptoSetting;
-
+
private String consensusProvider;
private Bytes consensusSettings;
-
+
private long createdTime;
@Override
@@ -55,11 +61,15 @@ public class LedgerInitSettingData implements LedgerInitSetting {
this.consensusSettings = consensusSettings;
}
+ public void setConsensusSettings(byte[] consensusSettings) {
+ this.consensusSettings = new Bytes(consensusSettings);
+ }
+
@Override
public String getConsensusProvider() {
return consensusProvider;
}
-
+
public void setConsensusProvider(String consensusProvider) {
this.consensusProvider = consensusProvider;
}
@@ -68,7 +78,7 @@ public class LedgerInitSettingData implements LedgerInitSetting {
public long getCreatedTime() {
return createdTime;
}
-
+
public void setCreatedTime(long createdTime) {
this.createdTime = createdTime;
}
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ParticipantOperator.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ParticipantOperator.java
new file mode 100644
index 00000000..83c1524a
--- /dev/null
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ParticipantOperator.java
@@ -0,0 +1,18 @@
+package com.jd.blockchain.transaction;
+
+public interface ParticipantOperator {
+
+ /**
+ * 注册参与方操作;
+ *
+ * @return
+ */
+ ParticipantRegisterOperationBuilder participants();
+
+ /**
+ * 参与方状态更新操作;
+ *
+ * @return
+ */
+ ParticipantStateUpdateOperationBuilder states();
+}
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ParticipantRegisterOpTemplate.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ParticipantRegisterOpTemplate.java
new file mode 100644
index 00000000..925b8338
--- /dev/null
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ParticipantRegisterOpTemplate.java
@@ -0,0 +1,41 @@
+package com.jd.blockchain.transaction;
+
+import com.jd.blockchain.binaryproto.DataContractRegistry;
+import com.jd.blockchain.crypto.PubKey;
+import com.jd.blockchain.ledger.BlockchainIdentity;
+import com.jd.blockchain.ledger.ParticipantInfo;
+import com.jd.blockchain.ledger.ParticipantRegisterOperation;
+import com.jd.blockchain.utils.net.NetworkAddress;
+
+public class ParticipantRegisterOpTemplate implements ParticipantRegisterOperation {
+
+ static {
+ DataContractRegistry.register(ParticipantRegisterOperation.class);
+ }
+
+ private String participantName;
+ private BlockchainIdentity participantRegisterIdentity;
+ private NetworkAddress networkAddress;
+
+ public ParticipantRegisterOpTemplate(String participantName, BlockchainIdentity participantRegisterIdentity, NetworkAddress networkAddress) {
+ this.participantName = participantName;
+ this.participantRegisterIdentity = participantRegisterIdentity;
+ this.networkAddress = networkAddress;
+
+ }
+
+ @Override
+ public String getParticipantName() {
+ return participantName;
+ }
+
+ @Override
+ public BlockchainIdentity getParticipantRegisterIdentity() {
+ return participantRegisterIdentity;
+ }
+
+ @Override
+ public NetworkAddress getNetworkAddress() {
+ return networkAddress;
+ }
+}
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ParticipantRegisterOperationBuilder.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ParticipantRegisterOperationBuilder.java
new file mode 100644
index 00000000..26f54c5b
--- /dev/null
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ParticipantRegisterOperationBuilder.java
@@ -0,0 +1,23 @@
+package com.jd.blockchain.transaction;
+
+import com.jd.blockchain.crypto.PubKey;
+import com.jd.blockchain.ledger.BlockchainIdentity;
+import com.jd.blockchain.ledger.ParticipantInfo;
+import com.jd.blockchain.ledger.ParticipantRegisterOperation;
+import com.jd.blockchain.utils.net.NetworkAddress;
+
+public interface ParticipantRegisterOperationBuilder {
+
+ /**
+ * 注册;
+ *
+ * @param
+ *
+ * @param
+ *
+ * @return
+ */
+ ParticipantRegisterOperation register(String participantName, BlockchainIdentity participantPubKey, NetworkAddress networkAddress);
+
+
+}
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ParticipantRegisterOperationBuilderImpl.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ParticipantRegisterOperationBuilderImpl.java
new file mode 100644
index 00000000..34b126d1
--- /dev/null
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ParticipantRegisterOperationBuilderImpl.java
@@ -0,0 +1,14 @@
+package com.jd.blockchain.transaction;
+
+import com.jd.blockchain.crypto.PubKey;
+import com.jd.blockchain.ledger.BlockchainIdentity;
+import com.jd.blockchain.ledger.ParticipantInfo;
+import com.jd.blockchain.ledger.ParticipantRegisterOperation;
+import com.jd.blockchain.utils.net.NetworkAddress;
+
+public class ParticipantRegisterOperationBuilderImpl implements ParticipantRegisterOperationBuilder {
+ @Override
+ public ParticipantRegisterOperation register(String participantName, BlockchainIdentity participantPubKey, NetworkAddress networkAddress) {
+ return new ParticipantRegisterOpTemplate(participantName, participantPubKey, networkAddress);
+ }
+}
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ParticipantStateOperator.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ParticipantStateOperator.java
new file mode 100644
index 00000000..22554031
--- /dev/null
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ParticipantStateOperator.java
@@ -0,0 +1,10 @@
+package com.jd.blockchain.transaction;
+
+public interface ParticipantStateOperator {
+ /**
+ * 参与方状态更新操作;
+ *
+ * @return
+ */
+ ParticipantStateUpdateOperationBuilder states();
+}
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ParticipantStateUpdateOpTemplate.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ParticipantStateUpdateOpTemplate.java
new file mode 100644
index 00000000..ff91eba5
--- /dev/null
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ParticipantStateUpdateOpTemplate.java
@@ -0,0 +1,41 @@
+package com.jd.blockchain.transaction;
+
+import com.jd.blockchain.binaryproto.DataContractRegistry;
+import com.jd.blockchain.ledger.BlockchainIdentity;
+import com.jd.blockchain.ledger.ParticipantNodeState;
+import com.jd.blockchain.ledger.ParticipantStateUpdateOperation;
+import com.jd.blockchain.utils.net.NetworkAddress;
+
+public class ParticipantStateUpdateOpTemplate implements ParticipantStateUpdateOperation {
+
+ static {
+ DataContractRegistry.register(ParticipantStateUpdateOperation.class);
+ }
+
+ private BlockchainIdentity stateUpdateIdentity;
+ private NetworkAddress networkAddress;
+ private ParticipantNodeState participantNodeState;
+
+ public ParticipantStateUpdateOpTemplate(BlockchainIdentity stateUpdateIdentity, NetworkAddress networkAddress, ParticipantNodeState participantNodeState) {
+
+ this.stateUpdateIdentity = stateUpdateIdentity;
+ this.networkAddress = networkAddress;
+ this.participantNodeState = participantNodeState;
+ }
+
+
+ @Override
+ public BlockchainIdentity getStateUpdateIdentity() {
+ return stateUpdateIdentity;
+ }
+
+ @Override
+ public NetworkAddress getNetworkAddress() {
+ return networkAddress;
+ }
+
+ @Override
+ public ParticipantNodeState getState() {
+ return participantNodeState;
+ }
+}
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ParticipantStateUpdateOperationBuilder.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ParticipantStateUpdateOperationBuilder.java
new file mode 100644
index 00000000..d6c69dc3
--- /dev/null
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ParticipantStateUpdateOperationBuilder.java
@@ -0,0 +1,21 @@
+package com.jd.blockchain.transaction;
+
+import com.jd.blockchain.ledger.BlockchainIdentity;
+import com.jd.blockchain.ledger.ParticipantNodeState;
+import com.jd.blockchain.ledger.ParticipantStateUpdateInfo;
+import com.jd.blockchain.ledger.ParticipantStateUpdateOperation;
+import com.jd.blockchain.utils.net.NetworkAddress;
+
+public interface ParticipantStateUpdateOperationBuilder {
+
+ /**
+ * 更新参与方状态,已注册->参与共识;
+ *
+ * @param
+ *
+ * @param
+ *
+ * @return
+ */
+ ParticipantStateUpdateOperation update(BlockchainIdentity blockchainIdentity, NetworkAddress networkAddress, ParticipantNodeState participantNodeState);
+}
\ No newline at end of file
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ParticipantStateUpdateOperationBuilderImpl.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ParticipantStateUpdateOperationBuilderImpl.java
new file mode 100644
index 00000000..9c84e181
--- /dev/null
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ParticipantStateUpdateOperationBuilderImpl.java
@@ -0,0 +1,15 @@
+package com.jd.blockchain.transaction;
+
+import com.jd.blockchain.ledger.BlockchainIdentity;
+import com.jd.blockchain.ledger.ParticipantNodeState;
+import com.jd.blockchain.ledger.ParticipantStateUpdateInfo;
+import com.jd.blockchain.ledger.ParticipantStateUpdateOperation;
+import com.jd.blockchain.utils.net.NetworkAddress;
+
+public class ParticipantStateUpdateOperationBuilderImpl implements ParticipantStateUpdateOperationBuilder {
+
+ @Override
+ public ParticipantStateUpdateOperation update(BlockchainIdentity blockchainIdentity, NetworkAddress networkAddress, ParticipantNodeState participantNodeState) {
+ return new ParticipantStateUpdateOpTemplate(blockchainIdentity, networkAddress, participantNodeState);
+ }
+}
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/PreparedTx.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/PreparedTx.java
index cb39f6b6..bba464e3 100644
--- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/PreparedTx.java
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/PreparedTx.java
@@ -7,13 +7,8 @@ import java.util.Comparator;
import org.springframework.cglib.proxy.UndeclaredThrowableException;
-import com.jd.blockchain.binaryproto.BinaryProtocol;
import com.jd.blockchain.crypto.AsymmetricKeypair;
-import com.jd.blockchain.crypto.Crypto;
import com.jd.blockchain.crypto.HashDigest;
-import com.jd.blockchain.crypto.PrivKey;
-import com.jd.blockchain.crypto.SignatureDigest;
-import com.jd.blockchain.crypto.SignatureFunction;
import com.jd.blockchain.ledger.DigitalSignature;
import com.jd.blockchain.ledger.OperationResult;
import com.jd.blockchain.ledger.PreparedTransaction;
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/RolePrivilegeConfigurer.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/RolePrivilegeConfigurer.java
new file mode 100644
index 00000000..13539536
--- /dev/null
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/RolePrivilegeConfigurer.java
@@ -0,0 +1,18 @@
+package com.jd.blockchain.transaction;
+
+import com.jd.blockchain.ledger.LedgerPermission;
+import com.jd.blockchain.ledger.TransactionPermission;
+
+public interface RolePrivilegeConfigurer extends RolesConfigure {
+
+ String getRoleName();
+
+ RolePrivilegeConfigurer disable(TransactionPermission... permissions);
+
+ RolePrivilegeConfigurer enable(TransactionPermission... permissions);
+
+ RolePrivilegeConfigurer disable(LedgerPermission... permissions);
+
+ RolePrivilegeConfigurer enable(LedgerPermission... permissions);
+
+}
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/RolesConfigure.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/RolesConfigure.java
new file mode 100644
index 00000000..4626fa5a
--- /dev/null
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/RolesConfigure.java
@@ -0,0 +1,7 @@
+package com.jd.blockchain.transaction;
+
+public interface RolesConfigure {
+
+ RolePrivilegeConfigurer configure(String roleName);
+
+}
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/RolesConfigureOpTemplate.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/RolesConfigureOpTemplate.java
new file mode 100644
index 00000000..ba5fc4e5
--- /dev/null
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/RolesConfigureOpTemplate.java
@@ -0,0 +1,139 @@
+package com.jd.blockchain.transaction;
+
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import com.jd.blockchain.binaryproto.DataContractRegistry;
+import com.jd.blockchain.ledger.LedgerPermission;
+import com.jd.blockchain.ledger.RolesConfigureOperation;
+import com.jd.blockchain.ledger.SecurityUtils;
+import com.jd.blockchain.ledger.TransactionPermission;
+import com.jd.blockchain.ledger.UserRegisterOperation;
+import com.jd.blockchain.utils.ArrayUtils;
+
+public class RolesConfigureOpTemplate implements RolesConfigurer, RolesConfigureOperation {
+
+ static {
+ DataContractRegistry.register(UserRegisterOperation.class);
+ DataContractRegistry.register(RolesConfigureOperation.class);
+ DataContractRegistry.register(RolePrivilegeEntry.class);
+ }
+
+ private Map
+ *
+ * 只能通过客户端接口直接操作;不支持通过合约操作;
+ *
+ * @author huanghaiquan
+ *
+ */
+public interface SecurityOperator {
+
+ /**
+ * 注册账户操作;
+ *
+ * @return
+ */
+
+ SecurityOperationBuilder security();
+
+}
\ No newline at end of file
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/TxBuilder.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/TxBuilder.java
index 1ff23a2f..0421b265 100644
--- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/TxBuilder.java
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/TxBuilder.java
@@ -75,6 +75,11 @@ public class TxBuilder implements TransactionBuilder {
public Collection