Browse Source

Implemented LedgerSecurityManager;

tags/1.1.0
huanghaiquan 5 years ago
parent
commit
bf1a71c4a2
41 changed files with 1569 additions and 529 deletions
  1. +4
    -0
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerAdminDataset.java
  2. +2
    -2
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerRepositoryImpl.java
  3. +7
    -32
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerSecurityManager.java
  4. +287
    -0
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerSecurityManagerImpl.java
  5. +3
    -35
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerTransactionalEditor.java
  6. +21
    -0
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MultiIdsPolicy.java
  7. +8
    -29
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/OperationHandle.java
  8. +8
    -2
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/OperationHandleContext.java
  9. +6
    -0
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/ParticipantDataset.java
  10. +6
    -3
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/RolePrivilegeDataset.java
  11. +38
    -0
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/SecurityContext.java
  12. +109
    -0
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/SecurityPolicy.java
  13. +120
    -24
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/TransactionBatchProcessor.java
  14. +13
    -13
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/TransactionEngineImpl.java
  15. +0
    -70
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/TransactionRequestContext.java
  16. +0
    -79
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/TransactionRequestContextImpl.java
  17. +115
    -0
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/TransactionRequestExtension.java
  18. +108
    -0
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/TransactionRequestExtensionImpl.java
  19. +63
    -0
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/UserRolesPrivileges.java
  20. +67
    -0
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/AbstractLedgerOperationHandle.java
  21. +22
    -7
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/AbtractContractEventHandle.java
  22. +20
    -25
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/ContractCodeDeployOperationHandle.java
  23. +17
    -25
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/DataAccountKVSetOperationHandle.java
  24. +21
    -28
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/DataAccountRegisterOperationHandle.java
  25. +0
    -8
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/JVMContractEventSendOperationHandle.java
  26. +18
    -18
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/UserRegisterOperationHandle.java
  27. +22
    -7
      source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/ContractInvokingTest.java
  28. +141
    -0
      source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/LedgerSecurityManagerTest.java
  29. +43
    -14
      source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/TransactionBatchProcessorTest.java
  30. +0
    -58
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/AbstractPrivilege.java
  31. +13
    -7
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/LedgerPrivilege.java
  32. +17
    -0
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/LedgerSecurityException.java
  33. +15
    -0
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ParticipantDoesNotExistException.java
  34. +121
    -0
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/PrivilegeBitset.java
  35. +65
    -0
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/Privileges.java
  36. +11
    -0
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/RolePrivilegeSettings.java
  37. +5
    -30
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/RolePrivileges.java
  38. +12
    -6
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionPrivilege.java
  39. +10
    -0
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionState.java
  40. +9
    -5
      source/tools/tools-mocker/src/main/java/com/jd/blockchain/mocker/MockerNodeContext.java
  41. +2
    -2
      source/tools/tools-mocker/src/main/java/com/jd/blockchain/mocker/handler/MockerContractExeHandle.java

+ 4
- 0
source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerAdminDataset.java View File

@@ -290,6 +290,10 @@ public class LedgerAdminDataset implements Transactional, LedgerAdminInfo {
return participants.getParticipants();
}
ParticipantDataset getParticipantDataset() {
return participants;
}
/**
* 加入新的参与方; 如果指定的参与方已经存在,则引发 LedgerException 异常;
*


+ 2
- 2
source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerRepositoryImpl.java View File

@@ -30,7 +30,7 @@ import com.jd.blockchain.utils.codec.Base58Utils;
* @author huanghaiquan
*
*/
public class LedgerRepositoryImpl implements LedgerRepository {
class LedgerRepositoryImpl implements LedgerRepository {

private static final Bytes LEDGER_PREFIX = Bytes.fromString("IDX" + LedgerConsts.KEY_SEPERATOR);

@@ -422,7 +422,7 @@ public class LedgerRepositoryImpl implements LedgerRepository {
private LedgerDataset innerGetLedgerDataset(LedgerBlock block) {
LedgerAdminDataset adminDataset = createAdminDataset(block);
CryptoSetting cryptoSetting = adminDataset.getSettings().getCryptoSetting();
UserAccountSet userAccountSet = createUserAccountSet(block, cryptoSetting);
DataAccountSet dataAccountSet = createDataAccountSet(block, cryptoSetting);
ContractAccountSet contractAccountSet = createContractAccountSet(block, cryptoSetting);


+ 7
- 32
source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerSecurityManager.java View File

@@ -2,37 +2,12 @@ package com.jd.blockchain.ledger.core;

import java.util.Set;

import com.jd.blockchain.ledger.LedgerPrivilege;
import com.jd.blockchain.ledger.RolePrivileges;
import com.jd.blockchain.utils.Bytes;

/**
*
* {@link LedgerSecurityManager} implements the functions of security
* management, including authentication, authorization, data confidentiality,
* etc.
*
* @author huanghaiquan
*
*/
public class LedgerSecurityManager {
public static final String ANONYMOUS_ROLE = "_ANONYMOUS";
public static final String DEFAULT_ROLE = "_DEFAULT";
public Set<String> getRoleNames(){
throw new IllegalStateException("Not implemented!");
}
public RolePrivileges setRole(String role, LedgerPrivilege privilege) {
throw new IllegalStateException("Not implemented!");
}
public interface LedgerSecurityManager {

public RolePrivileges getRole(String role) {
throw new IllegalStateException("Not implemented!");
}
}
String DEFAULT_ROLE = "_DEFAULT";

SecurityPolicy getSecurityPolicy(Set<Bytes> endpoints, Set<Bytes> nodes);

}

+ 287
- 0
source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerSecurityManagerImpl.java View File

@@ -0,0 +1,287 @@
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.Set;
import java.util.concurrent.ConcurrentHashMap;

import com.jd.blockchain.ledger.LedgerPermission;
import com.jd.blockchain.ledger.LedgerSecurityException;
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.UserRoleSettings;
import com.jd.blockchain.ledger.UserRoles;
import com.jd.blockchain.utils.Bytes;

/**
* 账本安全管理器;
*
* @author huanghaiquan
*
*/
public class LedgerSecurityManagerImpl implements LedgerSecurityManager {

private RolePrivilegeSettings rolePrivilegeSettings;

private UserRoleSettings userRolesSettings;

private Map<Bytes, UserRolesPrivileges> userPrivilegesCache = new ConcurrentHashMap<>();

private Map<Bytes, UserRoles> userRolesCache = new ConcurrentHashMap<>();
private Map<String, RolePrivileges> rolesPrivilegeCache = new ConcurrentHashMap<>();

public LedgerSecurityManagerImpl(RolePrivilegeSettings rolePrivilegeSettings, UserRoleSettings userRolesSettings) {
this.rolePrivilegeSettings = rolePrivilegeSettings;
this.userRolesSettings = userRolesSettings;
}

@Override
public SecurityPolicy getSecurityPolicy(Set<Bytes> endpoints, Set<Bytes> nodes) {

Map<Bytes, UserRolesPrivileges> endpointPrivilegeMap = new HashMap<>();
Map<Bytes, UserRolesPrivileges> nodePrivilegeMap = new HashMap<>();

for (Bytes userAddress : endpoints) {
UserRolesPrivileges userPrivileges = getUserRolesPrivilegs(userAddress);
endpointPrivilegeMap.put(userAddress, userPrivileges);
}

for (Bytes userAddress : nodes) {
UserRolesPrivileges userPrivileges = getUserRolesPrivilegs(userAddress);
nodePrivilegeMap.put(userAddress, userPrivileges);
}

return new UserRolesSecurityPolicy(endpointPrivilegeMap, nodePrivilegeMap);
}

private UserRolesPrivileges getUserRolesPrivilegs(Bytes userAddress) {
UserRolesPrivileges userPrivileges = userPrivilegesCache.get(userAddress);
if (userPrivileges != null) {
return userPrivileges;
}

UserRoles userRoles = null;

List<RolePrivileges> privilegesList = new ArrayList<>();

// 加载用户的角色列表;
userRoles = userRolesCache.get(userAddress);
if (userRoles == null) {
userRoles = userRolesSettings.getUserRoles(userAddress);
if (userRoles != null) {
userRolesCache.put(userAddress, userRoles);
}
}

// 计算用户的综合权限;
if (userRoles != null) {
String[] roles = userRoles.getRoles();
RolePrivileges privilege = null;
for (String role : roles) {
// 先从缓存读取,如果没有再从原始数据源进行加载;
privilege = rolesPrivilegeCache.get(role);
if (privilege == null) {
privilege = rolePrivilegeSettings.getRolePrivilege(role);
if (privilege == null) {
// 略过不存在的无效角色;
continue;
}
rolesPrivilegeCache.put(role, privilege);
}
privilegesList.add(privilege);
}
}
// 如果用户未被授权任何角色,则采用默认角色的权限;
if (privilegesList.size() == 0) {
RolePrivileges privilege = getDefaultRolePrivilege();
privilegesList.add(privilege);
}

if (userRoles == null) {
userPrivileges = new UserRolesPrivileges(userAddress, RolesPolicy.UNION, privilegesList);
} else {
userPrivileges = new UserRolesPrivileges(userAddress, userRoles.getPolicy(), privilegesList);
}

userPrivilegesCache.put(userAddress, userPrivileges);
return userPrivileges;
}

private RolePrivileges getDefaultRolePrivilege() {
RolePrivileges privileges = rolesPrivilegeCache.get(DEFAULT_ROLE);
if (privileges == null) {
privileges = rolePrivilegeSettings.getRolePrivilege(DEFAULT_ROLE);
if (privileges == null) {
throw new LedgerSecurityException(
"This ledger is missing the default role-privilege settings for the users who don't have a role!");
}
}
return privileges;
}

private class UserRolesSecurityPolicy implements SecurityPolicy {

/**
* 终端用户的权限表;
*/
private Map<Bytes, UserRolesPrivileges> endpointPrivilegeMap = new HashMap<>();

/**
* 节点参与方的权限表;
*/
private Map<Bytes, UserRolesPrivileges> nodePrivilegeMap = new HashMap<>();

public UserRolesSecurityPolicy(Map<Bytes, UserRolesPrivileges> endpointPrivilegeMap,
Map<Bytes, UserRolesPrivileges> nodePrivilegeMap) {
this.endpointPrivilegeMap = endpointPrivilegeMap;
this.nodePrivilegeMap = nodePrivilegeMap;
}

@Override
public boolean isEnableToEndpoints(LedgerPermission permission, MultiIdsPolicy midPolicy) {
if (MultiIdsPolicy.AT_LEAST_ONE == midPolicy) {
// 至少一个;
for (UserRolesPrivileges p : endpointPrivilegeMap.values()) {
if (p.getLedgerPrivileges().isEnable(permission)) {
return true;
}
}
return false;
} else if (MultiIdsPolicy.ALL == midPolicy) {
// 全部;
for (UserRolesPrivileges p : endpointPrivilegeMap.values()) {
if (!p.getLedgerPrivileges().isEnable(permission)) {
return false;
}
}
return true;
} else {
throw new IllegalArgumentException("Unsupported MultiIdsPolicy[" + midPolicy + "]!");
}
}

@Override
public boolean isEnableToEndpoints(TransactionPermission permission, MultiIdsPolicy midPolicy) {
if (MultiIdsPolicy.AT_LEAST_ONE == midPolicy) {
// 至少一个;
for (UserRolesPrivileges p : endpointPrivilegeMap.values()) {
if (p.getTransactionPrivileges().isEnable(permission)) {
return true;
}
}
return false;
} else if (MultiIdsPolicy.ALL == midPolicy) {
// 全部;
for (UserRolesPrivileges p : endpointPrivilegeMap.values()) {
if (!p.getTransactionPrivileges().isEnable(permission)) {
return false;
}
}
return true;
} else {
throw new IllegalArgumentException("Unsupported MultiIdsPolicy[" + midPolicy + "]!");
}
}

@Override
public boolean isEnableToNodes(LedgerPermission permission, MultiIdsPolicy midPolicy) {
if (MultiIdsPolicy.AT_LEAST_ONE == midPolicy) {
// 至少一个;
for (UserRolesPrivileges p : nodePrivilegeMap.values()) {
if (p.getLedgerPrivileges().isEnable(permission)) {
return true;
}
}
return false;
} else if (MultiIdsPolicy.ALL == midPolicy) {
// 全部;
for (UserRolesPrivileges p : nodePrivilegeMap.values()) {
if (!p.getLedgerPrivileges().isEnable(permission)) {
return false;
}
}
return true;
} else {
throw new IllegalArgumentException("Unsupported MultiIdsPolicy[" + midPolicy + "]!");
}
}

@Override
public boolean isEnableToNodes(TransactionPermission permission, MultiIdsPolicy midPolicy) {
if (MultiIdsPolicy.AT_LEAST_ONE == midPolicy) {
// 至少一个;
for (UserRolesPrivileges p : nodePrivilegeMap.values()) {
if (p.getTransactionPrivileges().isEnable(permission)) {
return true;
}
}
return false;
} else if (MultiIdsPolicy.ALL == midPolicy) {
// 全部;
for (UserRolesPrivileges p : nodePrivilegeMap.values()) {
if (!p.getTransactionPrivileges().isEnable(permission)) {
return false;
}
}
return true;
} else {
throw new IllegalArgumentException("Unsupported MultiIdsPolicy[" + midPolicy + "]!");
}
}

@Override
public void checkEndpoints(LedgerPermission permission, MultiIdsPolicy midPolicy)
throws LedgerSecurityException {
if (!isEnableToEndpoints(permission, midPolicy)) {
throw new LedgerSecurityException(String.format(
"The security policy [Permission=%s, Policy=%s] for endpoints rejected the current operation!",
permission, midPolicy));
}
}

@Override
public void checkEndpoints(TransactionPermission permission, MultiIdsPolicy midPolicy)
throws LedgerSecurityException {
if (!isEnableToEndpoints(permission, midPolicy)) {
throw new LedgerSecurityException(String.format(
"The security policy [Permission=%s, Policy=%s] for endpoints rejected the current operation!",
permission, midPolicy));
}
}

@Override
public void checkNodes(LedgerPermission permission, MultiIdsPolicy midPolicy) throws LedgerSecurityException {
if (!isEnableToNodes(permission, midPolicy)) {
throw new LedgerSecurityException(String.format(
"The security policy [Permission=%s, Policy=%s] for nodes rejected the current operation!",
permission, midPolicy));
}
}

@Override
public void checkNodes(TransactionPermission permission, MultiIdsPolicy midPolicy)
throws LedgerSecurityException {
if (!isEnableToNodes(permission, midPolicy)) {
throw new LedgerSecurityException(String.format(
"The security policy [Permission=%s, Policy=%s] for nodes rejected the current operation!",
permission, midPolicy));
}
}

@Override
public Set<Bytes> getEndpoints() {
return endpointPrivilegeMap.keySet();
}

@Override
public Set<Bytes> getNodes() {
return nodePrivilegeMap.keySet();
}

}

}

+ 3
- 35
source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerTransactionalEditor.java View File

@@ -214,32 +214,9 @@ public class LedgerTransactionalEditor implements LedgerEditor {
return ledgerHash.equals(reqLedgerHash);
}

private boolean verifyTxContent(TransactionRequest request) {
TransactionContent txContent = request.getTransactionContent();
if (!TxBuilder.verifyTxContentHash(txContent, txContent.getHash())) {
return false;
}
DigitalSignature[] endpointSignatures = request.getEndpointSignatures();
if (endpointSignatures != null) {
for (DigitalSignature signature : endpointSignatures) {
if (!SignatureUtils.verifyHashSignature(txContent.getHash(), signature.getDigest(),
signature.getPubKey())) {
return false;
}
}
}
DigitalSignature[] nodeSignatures = request.getNodeSignatures();
if (nodeSignatures != null) {
for (DigitalSignature signature : nodeSignatures) {
if (!SignatureUtils.verifyHashSignature(txContent.getHash(), signature.getDigest(),
signature.getPubKey())) {
return false;
}
}
}
return true;
}

/**
* 注:此方法不验证交易完整性和签名有效性,仅仅设计为进行交易记录的管理;调用者应在此方法之外进行数据完整性和签名有效性的检查;
*/
@Override
public synchronized LedgerTransactionContext newTransaction(TransactionRequest txRequest) {
// if (SettingContext.txSettings().verifyLedger() && !isRequestMatched(txRequest)) {
@@ -250,15 +227,6 @@ public class LedgerTransactionalEditor implements LedgerEditor {
TransactionState.IGNORED_BY_WRONG_LEDGER);
}

// TODO: 把验签和创建交易并行化;
// if (SettingContext.txSettings().verifySignature() && !verifyTxContent(txRequest)) {
if (!verifyTxContent(txRequest)) {
// 抛弃哈希和签名校验失败的交易请求;
throw new IllegalTransactionException(
"Wrong transaction signature! --[TxHash=" + txRequest.getTransactionContent().getHash() + "]!",
TransactionState.IGNORED_BY_WRONG_CONTENT_SIGNATURE);
}

if (currentTxCtx != null) {
throw new IllegalStateException(
"Unable to open another new transaction before the current transaction is completed! --[TxHash="


+ 21
- 0
source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MultiIdsPolicy.java View File

@@ -0,0 +1,21 @@
package com.jd.blockchain.ledger.core;

/**
* 多身份的权限校验策略;
*
* @author huanghaiquan
*
*/
public enum MultiIdsPolicy {

/**
* 至少有一个都能通过;
*/
AT_LEAST_ONE,

/**
* 每一个都能通过;
*/
ALL

}

+ 8
- 29
source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/OperationHandle.java View File

@@ -3,7 +3,6 @@ package com.jd.blockchain.ledger.core;
import com.jd.blockchain.ledger.BytesValue;
import com.jd.blockchain.ledger.Operation;


public interface OperationHandle {

/**
@@ -18,36 +17,16 @@ public interface OperationHandle {
* 同步解析和执行操作;
*
*
* @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,
BytesValue process(Operation op, LedgerDataset newBlockDataset, TransactionRequestExtension requestContext,
LedgerDataset previousBlockDataset, OperationHandleContext handleContext, LedgerService ledgerService);

// /**
// * 异步解析和执行操作;
// * TODO 未来规划实现
// *
// *
// * @param op
// * 操作实例;
// * @param newBlockDataset
// * 需要修改的新区块的数据集;
// * @param requestContext
// * 交易请求上下文;
// * @param previousBlockDataset
// * 新区块的前一个区块的数据集;即未提交新区块之前的经过共识的账本最新数据集;
// *
// * @return 操作执行结果
// */
// AsyncFuture<byte[]> asyncProcess(Operation op, LedgerDataSet newBlockDataset, TransactionRequestContext requestContext,
// LedgerDataSet previousBlockDataset, OperationHandleContext handleContext, LedgerService ledgerService);
}

+ 8
- 2
source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/OperationHandleContext.java View File

@@ -2,8 +2,14 @@ package com.jd.blockchain.ledger.core;

import com.jd.blockchain.ledger.Operation;

/**
* 在交易处理过程中,提供对多种交易操作处理器互相调用的机制;
*
* @author huanghaiquan
*
*/
public interface OperationHandleContext {
void handle(Operation operation);
}

+ 6
- 0
source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/ParticipantDataset.java View File

@@ -77,6 +77,12 @@ public class ParticipantDataset implements Transactional, MerkleProvable {
return address;
}

public boolean contains(Bytes address) {
Bytes key = encodeKey(address);
long latestVersion = dataset.getVersion(key);
return latestVersion > -1;
}

/**
* 返回指定地址的参与方凭证;
*


+ 6
- 3
source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/RolePrivilegeDataset.java View File

@@ -7,6 +7,7 @@ import com.jd.blockchain.ledger.LedgerException;
import com.jd.blockchain.ledger.LedgerPermission;
import com.jd.blockchain.ledger.LedgerPrivilege;
import com.jd.blockchain.ledger.PrivilegeSet;
import com.jd.blockchain.ledger.Privileges;
import com.jd.blockchain.ledger.RolePrivilegeSettings;
import com.jd.blockchain.ledger.RolePrivileges;
import com.jd.blockchain.ledger.TransactionPermission;
@@ -61,9 +62,11 @@ public class RolePrivilegeDataset implements Transactional, MerkleProvable, Role
return dataset.getDataCount();
}

/**
*
*/
@Override
public long addRolePrivilege(String roleName, Privileges privileges) {
return addRolePrivilege(roleName, privileges.getLedgerPrivilege(), privileges.getTransactionPrivilege());
}

@Override
public long addRolePrivilege(String roleName, LedgerPrivilege ledgerPrivilege, TransactionPrivilege txPrivilege) {
RolePrivileges roleAuth = new RolePrivileges(roleName, -1, ledgerPrivilege, txPrivilege);


+ 38
- 0
source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/SecurityContext.java View File

@@ -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<SecurityPolicy> policyHolder = new ThreadLocal<SecurityPolicy>();

public static void setContextUsersPolicy(SecurityPolicy policy) {
policyHolder.set(policy);
}

public static SecurityPolicy removeContextUsersPolicy() {
SecurityPolicy p = policyHolder.get();
policyHolder.remove();
return p;
}

public static SecurityPolicy getContextUsersPolicy() {
return policyHolder.get();
}

/**
* 把上下文安全策略切换为指定的策略,并执行参数指定的 {@link Runnable} 操作,当操作完成后恢复原来的上下文策略;
*
* @param contextUsersPolicy
* @param runnable
*/
public static void switchContextUsersPolicy(SecurityPolicy contextUsersPolicy, Runnable runnable) {

}

}

+ 109
- 0
source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/SecurityPolicy.java View File

@@ -0,0 +1,109 @@
package com.jd.blockchain.ledger.core;

import java.util.Set;

import com.jd.blockchain.ledger.LedgerPermission;
import com.jd.blockchain.ledger.LedgerSecurityException;
import com.jd.blockchain.ledger.TransactionPermission;
import com.jd.blockchain.ledger.TransactionRequest;
import com.jd.blockchain.utils.Bytes;

/**
* 针对特定交易请求的账本安全策略;
*
* @author huanghaiquan
*
*/
public interface SecurityPolicy {

/**
* 签署交易的终端用户的地址列表;(来自{@link TransactionRequest#getEndpointSignatures()})
*
* @return
*/
Set<Bytes> getEndpoints();

/**
* 签署交易的节点参与方的地址列表(来自{@link TransactionRequest#getNodeSignatures()})
*
* @return
*/
Set<Bytes> getNodes();

/**
* 检查签署交易的终端用户(来自{@link TransactionRequest#getEndpointSignatures()})是否被授权了参数指定的权限;<br>
*
* @param permission 要检查的权限;
* @param midPolicy 针对多个签名用户的权限策略;
* @return 返回 true 表示获得授权; 返回 false 表示未获得授权;
*/
boolean isEnableToEndpoints(LedgerPermission permission, MultiIdsPolicy midPolicy);

/**
* 检查签署交易的终端用户(来自{@link TransactionRequest#getEndpointSignatures()})是否被授权了参数指定的权限;<br>
*
* @param permission 要检查的权限;
* @param midPolicy 针对多个签名用户的权限策略;
* @return 返回 true 表示获得授权; 返回 false 表示未获得授权;
*/
boolean isEnableToEndpoints(TransactionPermission permission, MultiIdsPolicy midPolicy);

/**
* 检查签署交易的节点参与方(来自{@link TransactionRequest#getNodeSignatures()})是否被授权了参数指定的权限;<br>
*
* @param permission 要检查的权限;
* @param midPolicy 针对多个签名用户的权限策略;
* @return 返回 true 表示获得授权; 返回 false 表示未获得授权;
*/
boolean isEnableToNodes(LedgerPermission permission, MultiIdsPolicy midPolicy);

/**
* 检查签署交易的节点参与方(来自{@link TransactionRequest#getNodeSignatures()})是否被授权了参数指定的权限;<br>
*
* @param permission 要检查的权限;
* @param midPolicy 针对多个签名用户的权限策略;
* @return 返回 true 表示获得授权; 返回 false 表示未获得授权;
*/
boolean isEnableToNodes(TransactionPermission permission, MultiIdsPolicy midPolicy);

/**
* 检查签署交易的终端用户(来自{@link TransactionRequest#getEndpointSignatures()})是否被授权了参数指定的权限;<br>
* 如果未获授权,方法将引发 {@link LedgerSecurityException} 异常;
*
* @param permission 要检查的权限;
* @param midPolicy 针对多个签名用户的权限策略;
* @throws LedgerSecurityException
*/
void checkEndpoints(LedgerPermission permission, MultiIdsPolicy midPolicy) throws LedgerSecurityException;

/**
* 检查签署交易的终端用户(来自{@link TransactionRequest#getEndpointSignatures()})是否被授权了参数指定的权限;<br>
* 如果未获授权,方法将引发 {@link LedgerSecurityException} 异常;
*
* @param permission
* @param midPolicy
* @throws LedgerSecurityException
*/
void checkEndpoints(TransactionPermission permission, MultiIdsPolicy midPolicy) throws LedgerSecurityException;

/**
* 检查签署交易的节点参与方(来自{@link TransactionRequest#getNodeSignatures()})是否被授权了参数指定的权限;<br>
* 如果未获授权,方法将引发 {@link LedgerSecurityException} 异常;
*
* @param permission
* @param midPolicy
* @throws LedgerSecurityException
*/
void checkNodes(LedgerPermission permission, MultiIdsPolicy midPolicy) throws LedgerSecurityException;

/**
* 检查签署交易的节点参与方(来自{@link TransactionRequest#getNodeSignatures()})是否被授权了参数指定的权限;<br>
* 如果未获授权,方法将引发 {@link LedgerSecurityException} 异常;
*
* @param permission
* @param midPolicy
* @throws LedgerSecurityException
*/
void checkNodes(TransactionPermission permission, MultiIdsPolicy midPolicy) throws LedgerSecurityException;

}

+ 120
- 24
source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/TransactionBatchProcessor.java View File

@@ -1,6 +1,7 @@
package com.jd.blockchain.ledger.core;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;

@@ -15,24 +16,32 @@ 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.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 LedgerSecurityManager securityManager;

private LedgerService ledgerService;

private LedgerEditor newBlockEditor;
@@ -55,8 +64,9 @@ public class TransactionBatchProcessor implements TransactionBatchProcess {
* @param previousBlockDataset 新区块的前一个区块的数据集;即未提交新区块之前的经过共识的账本最新数据集;
* @param opHandles 操作处理对象注册表;
*/
public TransactionBatchProcessor(LedgerEditor newBlockEditor, LedgerDataset previousBlockDataset,
OperationHandleRegisteration opHandles, LedgerService ledgerService) {
public TransactionBatchProcessor(LedgerSecurityManager securityManager, LedgerEditor newBlockEditor,
LedgerDataset previousBlockDataset, OperationHandleRegisteration opHandles, LedgerService ledgerService) {
this.securityManager = securityManager;
this.newBlockEditor = newBlockEditor;
this.previousBlockDataset = previousBlockDataset;
this.opHandles = opHandles;
@@ -76,12 +86,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.getSecurityPolicy(reqExt.getEndpointAddresses(),
reqExt.getNodeAddresses());
SecurityContext.setContextUsersPolicy(securityPolicy);

// 安全校验;
checkSecurity();

// 验证交易请求;
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());
@@ -93,10 +117,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(),
@@ -110,12 +133,86 @@ 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 = SecurityContext.getContextUsersPolicy();

// 验证当前交易请求的节点参与方是否具有权限;
securityPolicy.checkNodes(LedgerPermission.APPROVE_TX, MultiIdsPolicy.AT_LEAST_ONE);
}

private void checkRequest(TransactionRequestExtension reqExt) {
// TODO: 把验签和创建交易并行化;
checkTxContent(reqExt);
checkEndpointSignatures(reqExt);
checkNodeSignatures(reqExt);
}

private void checkTxContent(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 checkEndpointSignatures(TransactionRequestExtension request) {
TransactionContent txContent = request.getTransactionContent();
Collection<Credential> endpoints = request.getEndpoints();
if (endpoints != null) {
for (Credential endpoint : endpoints) {
if (!previousBlockDataset.getUserAccountSet().contains(endpoint.getAddress())) {
throw new UserDoesNotExistException(
"The endpoint signer[" + endpoint.getAddress() + "] was not registered!");
}

if (!SignatureUtils.verifyHashSignature(txContent.getHash(), endpoint.getSignature().getDigest(),
endpoint.getPubKey())) {
// 由于签名校验失败,引发IllegalTransactionException,使外部调用抛弃此交易请求;
throw new IllegalTransactionException(
String.format("Wrong transaction endpoint signature! --[Tx Hash=%s][Endpoint Signer=%s]!",
request.getTransactionContent().getHash(), endpoint.getAddress()),
TransactionState.IGNORED_BY_WRONG_CONTENT_SIGNATURE);
}
}
}
}

private void checkNodeSignatures(TransactionRequestExtension request) {
TransactionContent txContent = request.getTransactionContent();
Collection<Credential> nodes = request.getNodes();
if (nodes != null) {
for (Credential node : nodes) {
if (!previousBlockDataset.getAdminDataset().getParticipantDataset().contains(node.getAddress())) {
throw new ParticipantDoesNotExistException(
"The node signer[" + node.getAddress() + "] was not registered to the participant set!");
}

if (!SignatureUtils.verifyHashSignature(txContent.getHash(), node.getSignature().getDigest(),
node.getPubKey())) {
// 由于签名校验失败,引发IllegalTransactionException,使外部调用抛弃此交易请求;
throw new IllegalTransactionException(
String.format("Wrong transaction node signature! --[Tx Hash=%s][Node Signer=%s]!",
request.getTransactionContent().getHash(), node.getAddress()),
TransactionState.IGNORED_BY_WRONG_CONTENT_SIGNATURE);
}
}
}
}

/**
* 处理交易;<br>
*
@@ -125,23 +222,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<OperationResult> operationResults = new ArrayList<>();
try {
LedgerDataset dataset = txCtx.getDataset();
TransactionRequestContext reqCtx = new TransactionRequestContextImpl(request);
// TODO: 验证签名者的有效性;
for (Bytes edpAddr : reqCtx.getEndpoints()) {
if (!previousBlockDataset.getUserAccountSet().contains(edpAddr)) {
throw new LedgerException("The endpoint signer[" + edpAddr + "] was not registered!");
}
}
for (Bytes edpAddr : reqCtx.getNodes()) {
if (!previousBlockDataset.getUserAccountSet().contains(edpAddr)) {
throw new LedgerException("The node signer[" + edpAddr + "] was not registered!");
}
}

// 执行操作;
Operation[] ops = request.getTransactionContent().getOperations();
@@ -151,14 +236,14 @@ public class TransactionBatchProcessor implements TransactionBatchProcess {
// assert; Instance of operation are one of User related operations or
// DataAccount related operations;
OperationHandle hdl = opHandles.getHandle(operation.getClass());
hdl.process(operation, dataset, reqCtx, previousBlockDataset, this, ledgerService);
hdl.process(operation, dataset, request, previousBlockDataset, this, ledgerService);
}
};
OperationHandle opHandle;
int opIndex = 0;
for (Operation op : ops) {
opHandle = opHandles.getHandle(op.getClass());
BytesValue opResult = opHandle.process(op, dataset, reqCtx, previousBlockDataset, handleContext,
BytesValue opResult = opHandle.process(op, dataset, request, previousBlockDataset, handleContext,
ledgerService);
if (opResult != null) {
operationResults.add(new OperationResultData(opIndex, opResult));
@@ -177,6 +262,7 @@ public class TransactionBatchProcessor implements TransactionBatchProcess {
newBlockEditor.getBlockHeight(), request.getHash(), request.getTransactionContent().getHash(),
e.getMessage()), e);
} catch (BlockRollbackException e) {
// 回滚整个区块;
result = TransactionState.IGNORED_BY_BLOCK_FULL_ROLLBACK;
txCtx.rollback();
LOGGER.error(
@@ -195,17 +281,27 @@ public class TransactionBatchProcessor implements TransactionBatchProcess {
result = TransactionState.USER_DOES_NOT_EXIST;
} else if (e instanceof ContractDoesNotExistException) {
result = TransactionState.CONTRACT_DOES_NOT_EXIST;
} else if (e instanceof ParticipantDoesNotExistException) {
result = TransactionState.PARTICIPANT_DOES_NOT_EXIST;
}
txCtx.discardAndCommit(result, operationResults);
LOGGER.error(String.format(
"Due to ledger exception, the data changes resulting from the transaction will be rolled back and the results of the transaction will be committed! --[BlockHeight=%s][RequestHash=%s][TxHash=%s] --%s",
"Due to ledger exception, the data changes resulting from transaction execution will be rolled back and the results of the transaction will be committed! --[BlockHeight=%s][RequestHash=%s][TxHash=%s] --%s",
newBlockEditor.getBlockHeight(), request.getHash(), request.getTransactionContent().getHash(),
e.getMessage()), e);
} catch (LedgerSecurityException e) {
// TODO: 识别更详细的异常类型以及执行对应的处理;
result = TransactionState.REJECTED_BY_SECURITY_POLICY;
txCtx.discardAndCommit(result, operationResults);
LOGGER.error(String.format(
"Due to ledger security exception, the data changes resulting from transaction execution will be rolled back and the results of the transaction will be committed! --[BlockHeight=%s][RequestHash=%s][TxHash=%s] --%s",
newBlockEditor.getBlockHeight(), request.getHash(), request.getTransactionContent().getHash(),
e.getMessage()), e);
} catch (Exception e) {
result = TransactionState.SYSTEM_ERROR;
txCtx.discardAndCommit(TransactionState.SYSTEM_ERROR, operationResults);
LOGGER.error(String.format(
"Due to system exception, the data changes resulting from the transaction will be rolled back and the results of the transaction will be committed! --[BlockHeight=%s][RequestHash=%s][TxHash=%s] --%s",
"Due to system exception, the data changes resulting from transaction execution will be rolled back and the results of the transaction will be committed! --[BlockHeight=%s][RequestHash=%s][TxHash=%s] --%s",
newBlockEditor.getBlockHeight(), request.getHash(), request.getTransactionContent().getHash(),
e.getMessage()), e);
}


+ 13
- 13
source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/TransactionEngineImpl.java View File

@@ -41,8 +41,12 @@ public class TransactionEngineImpl implements TransactionEngine {
LedgerBlock ledgerBlock = ledgerRepo.getLatestBlock();
LedgerEditor newBlockEditor = ledgerRepo.createNextBlock();
LedgerDataset previousBlockDataset = ledgerRepo.getDataSet(ledgerBlock);
batch = new InnerTransactionBatchProcessor(ledgerHash, newBlockEditor, previousBlockDataset, opHdlRegs,
ledgerService, ledgerBlock.getHeight());

LedgerAdminDataset previousAdminDataset = previousBlockDataset.getAdminDataset();
LedgerSecurityManager securityManager = new LedgerSecurityManagerImpl(previousAdminDataset.getRolePrivileges(),
previousAdminDataset.getUserRoles());
batch = new InnerTransactionBatchProcessor(ledgerHash, securityManager, newBlockEditor, previousBlockDataset,
opHdlRegs, ledgerService, ledgerBlock.getHeight());
batchs.put(ledgerHash, batch);
return batch;
}
@@ -65,19 +69,15 @@ public class TransactionEngineImpl implements TransactionEngine {
/**
* 创建交易批处理器;
*
* @param ledgerHash
* 账本哈希;
* @param newBlockEditor
* 新区块的数据编辑器;
* @param previousBlockDataset
* 新区块的前一个区块的数据集;即未提交新区块之前的经过共识的账本最新数据集;
* @param opHandles
* 操作处理对象注册表;
* @param ledgerHash 账本哈希;
* @param newBlockEditor 新区块的数据编辑器;
* @param previousBlockDataset 新区块的前一个区块的数据集;即未提交新区块之前的经过共识的账本最新数据集;
* @param opHandles 操作处理对象注册表;
*/
public InnerTransactionBatchProcessor(HashDigest ledgerHash, LedgerEditor newBlockEditor,
LedgerDataset previousBlockDataset, OperationHandleRegisteration opHandles,
public InnerTransactionBatchProcessor(HashDigest ledgerHash, LedgerSecurityManager securityManager,
LedgerEditor newBlockEditor, LedgerDataset previousBlockDataset, OperationHandleRegisteration opHandles,
LedgerService ledgerService, long blockHeight) {
super(newBlockEditor, previousBlockDataset, opHandles, ledgerService);
super(securityManager, newBlockEditor, previousBlockDataset, opHandles, ledgerService);
this.ledgerHash = ledgerHash;
this.blockHeight = blockHeight;
}


+ 0
- 70
source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/TransactionRequestContext.java View File

@@ -1,70 +0,0 @@
package com.jd.blockchain.ledger.core;

import java.util.Set;

import com.jd.blockchain.ledger.DigitalSignature;
import com.jd.blockchain.ledger.TransactionRequest;
import com.jd.blockchain.utils.Bytes;

/**
* 交易请求上下文;
*
* @author huanghaiquan
*
*/
public interface TransactionRequestContext {

/**
* 交易请求;
*
* @return
*/
TransactionRequest getRequest();

/**
* 签名发起请求的终端用户的地址列表;
*
* @return
*/
Set<Bytes> getEndpoints();

/**
* 签名发起请求的节点的地址列表;
*
* @return
*/
Set<Bytes> getNodes();
/**
* 请求的终端发起人列表中是否包含指定地址的终端用户;
*
* @param address
* @return
*/
boolean containsEndpoint(Bytes address);
/**
* 请求的经手节点列表中是否包含指定地址的节点;
*
* @param address
* @return
*/
boolean containsNode(Bytes address);

/**
* 获取交易请求中指定地址的终端的签名;
*
* @param address
* @return
*/
DigitalSignature getEndpointSignature(Bytes address);

/**
* 获取交易请求中指定地址的节点的签名;
*
* @param address
* @return
*/
DigitalSignature getNodeSignature(Bytes address);

}

+ 0
- 79
source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/TransactionRequestContextImpl.java View File

@@ -1,79 +0,0 @@
package com.jd.blockchain.ledger.core;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import com.jd.blockchain.crypto.AddressEncoding;
import com.jd.blockchain.ledger.DigitalSignature;
import com.jd.blockchain.ledger.TransactionRequest;
import com.jd.blockchain.utils.Bytes;

/**
* @Author zhaogw
* @Date 2018/9/5 14:52
*/
public class TransactionRequestContextImpl implements TransactionRequestContext {

private TransactionRequest request;

private Map<Bytes, DigitalSignature> endpointSignatures = new HashMap<>();

private Map<Bytes, DigitalSignature> nodeSignatures = new HashMap<>();

public TransactionRequestContextImpl(TransactionRequest request) {
this.request = request;
resolveSigners();
}

private void resolveSigners() {
if (request.getEndpointSignatures() != null) {
for (DigitalSignature signature : request.getEndpointSignatures()) {
Bytes address = AddressEncoding.generateAddress(signature.getPubKey());
endpointSignatures.put(address, signature);
}
}
if (request.getEndpointSignatures() != null) {
for (DigitalSignature signature : request.getNodeSignatures()) {
Bytes address = AddressEncoding.generateAddress(signature.getPubKey());
nodeSignatures.put(address, signature);
}
}
}

@Override
public TransactionRequest getRequest() {
return request;
}

@Override
public Set<Bytes> getEndpoints() {
return endpointSignatures.keySet();
}

@Override
public Set<Bytes> getNodes() {
return nodeSignatures.keySet();
}

@Override
public boolean containsEndpoint(Bytes address) {
return endpointSignatures.containsKey(address);
}

@Override
public boolean containsNode(Bytes address) {
return nodeSignatures.containsKey(address);
}

@Override
public DigitalSignature getEndpointSignature(Bytes address) {
return endpointSignatures.get(address);
}

@Override
public DigitalSignature getNodeSignature(Bytes address) {
return nodeSignatures.get(address);
}

}

+ 115
- 0
source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/TransactionRequestExtension.java View File

@@ -0,0 +1,115 @@
package com.jd.blockchain.ledger.core;

import java.util.Collection;
import java.util.Set;

import com.jd.blockchain.crypto.PubKey;
import com.jd.blockchain.ledger.BlockchainIdentity;
import com.jd.blockchain.ledger.BlockchainIdentityData;
import com.jd.blockchain.ledger.DigitalSignature;
import com.jd.blockchain.ledger.TransactionRequest;
import com.jd.blockchain.utils.Bytes;

/**
* 交易请求上下文;
*
* @author huanghaiquan
*
*/
public interface TransactionRequestExtension extends TransactionRequest {

// /**
// * 交易请求;
// *
// * @return
// */
// TransactionRequest getRequest();

/**
* 签名发起请求的终端用户的地址列表;
*
* @return
*/
Set<Bytes> getEndpointAddresses();

/**
* 签名发起请求的终端用户列表;
*
* @return
*/
Collection<Credential> getEndpoints();

/**
* 签名发起请求的节点的地址列表;
*
* @return
*/
Set<Bytes> getNodeAddresses();

/**
* 签名发起请求的节点列表;
*
* @return
*/
Collection<Credential> getNodes();

/**
* 请求的终端发起人列表中是否包含指定地址的终端用户;
*
* @param address
* @return
*/
boolean containsEndpoint(Bytes address);

/**
* 请求的经手节点列表中是否包含指定地址的节点;
*
* @param address
* @return
*/
boolean containsNode(Bytes address);

/**
* 获取交易请求中指定地址的终端的签名;
*
* @param address
* @return
*/
DigitalSignature getEndpointSignature(Bytes address);

/**
* 获取交易请求中指定地址的节点的签名;
*
* @param address
* @return
*/
DigitalSignature getNodeSignature(Bytes address);

public static class Credential {

private final BlockchainIdentity identity;

private final DigitalSignature signature;

Credential(DigitalSignature signature) {
this.identity = new BlockchainIdentityData(signature.getPubKey());
this.signature = signature;
}

public Bytes getAddress() {
return identity.getAddress();
}
public PubKey getPubKey() {
return identity.getPubKey();
}

public BlockchainIdentity getIdentity() {
return identity;
}

public DigitalSignature getSignature() {
return signature;
}
}
}

+ 108
- 0
source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/TransactionRequestExtensionImpl.java View File

@@ -0,0 +1,108 @@
package com.jd.blockchain.ledger.core;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.ledger.DigitalSignature;
import com.jd.blockchain.ledger.TransactionContent;
import com.jd.blockchain.ledger.TransactionRequest;
import com.jd.blockchain.utils.Bytes;

/**
* 交易请求的扩展信息;
*
* @author huanghaiquan
*
*/
public class TransactionRequestExtensionImpl implements TransactionRequestExtension {

private TransactionRequest request;

private Map<Bytes, Credential> endpointSignatures = new HashMap<>();

private Map<Bytes, Credential> nodeSignatures = new HashMap<>();

public TransactionRequestExtensionImpl(TransactionRequest request) {
this.request = request;
resolveSigners();
}

private void resolveSigners() {
if (request.getEndpointSignatures() != null) {
for (DigitalSignature signature : request.getEndpointSignatures()) {
Credential cred = new Credential(signature);
endpointSignatures.put(cred.getIdentity().getAddress(), cred);
}
}
if (request.getEndpointSignatures() != null) {
for (DigitalSignature signature : request.getNodeSignatures()) {
Credential cred = new Credential(signature);
nodeSignatures.put(cred.getIdentity().getAddress(), cred);
}
}
}

@Override
public Set<Bytes> getEndpointAddresses() {
return endpointSignatures.keySet();
}

@Override
public Set<Bytes> getNodeAddresses() {
return nodeSignatures.keySet();
}

@Override
public Collection<Credential> getEndpoints() {
return endpointSignatures.values();
}

@Override
public Collection<Credential> getNodes() {
return nodeSignatures.values();
}

@Override
public boolean containsEndpoint(Bytes address) {
return endpointSignatures.containsKey(address);
}

@Override
public boolean containsNode(Bytes address) {
return nodeSignatures.containsKey(address);
}

@Override
public DigitalSignature getEndpointSignature(Bytes address) {
return endpointSignatures.get(address).getSignature();
}

@Override
public DigitalSignature getNodeSignature(Bytes address) {
return nodeSignatures.get(address).getSignature();
}

@Override
public HashDigest getHash() {
return request.getHash();
}

@Override
public DigitalSignature[] getNodeSignatures() {
return request.getNodeSignatures();
}

@Override
public DigitalSignature[] getEndpointSignatures() {
return request.getEndpointSignatures();
}

@Override
public TransactionContent getTransactionContent() {
return request.getTransactionContent();
}

}

+ 63
- 0
source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/UserRolesPrivileges.java View File

@@ -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 PrivilegeBitset<LedgerPermission> ledgerPrivileges;

private PrivilegeBitset<TransactionPermission> transactionPrivileges;

public UserRolesPrivileges(Bytes userAddress, RolesPolicy policy, Collection<RolePrivileges> privilegesList) {
this.userAddress = userAddress;
LedgerPrivilege[] ledgerPrivileges = privilegesList.stream().map(p -> p.getLedgerPrivilege())
.toArray(LedgerPrivilege[]::new);
TransactionPrivilege[] transactionPrivileges = privilegesList.stream().map(p -> p.getTransactionPrivilege())
.toArray(TransactionPrivilege[]::new);

this.ledgerPrivileges = ledgerPrivileges[0].clone();
this.transactionPrivileges = transactionPrivileges[0].clone();

if (policy == RolesPolicy.UNION) {
this.ledgerPrivileges.union(ledgerPrivileges, 1, ledgerPrivileges.length - 1);
this.transactionPrivileges.union(transactionPrivileges, 1, transactionPrivileges.length - 1);

} else if (policy == RolesPolicy.INTERSECT) {
this.ledgerPrivileges.intersect(ledgerPrivileges, 1, ledgerPrivileges.length - 1);
this.transactionPrivileges.intersect(transactionPrivileges, 1, transactionPrivileges.length - 1);
} else {
throw new IllegalStateException("Unsupported roles policy[" + policy.toString() + "]!");
}

}

public Bytes getUserAddress() {
return userAddress;
}

public PrivilegeBitset<LedgerPermission> getLedgerPrivileges() {
return ledgerPrivileges;
}

public PrivilegeBitset<TransactionPermission> getTransactionPrivileges() {
return transactionPrivileges;
}

}

+ 67
- 0
source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/AbstractLedgerOperationHandle.java View File

@@ -0,0 +1,67 @@
package com.jd.blockchain.ledger.core.handles;

import com.jd.blockchain.binaryproto.DataContractRegistry;
import com.jd.blockchain.ledger.BytesValue;
import com.jd.blockchain.ledger.Operation;
import com.jd.blockchain.ledger.TransactionPermission;
import com.jd.blockchain.ledger.core.LedgerDataset;
import com.jd.blockchain.ledger.core.LedgerService;
import com.jd.blockchain.ledger.core.MultiIdsPolicy;
import com.jd.blockchain.ledger.core.OperationHandle;
import com.jd.blockchain.ledger.core.OperationHandleContext;
import com.jd.blockchain.ledger.core.SecurityContext;
import com.jd.blockchain.ledger.core.SecurityPolicy;
import com.jd.blockchain.ledger.core.TransactionRequestExtension;

/**
* 执行直接账本操作的处理类;
*
* @author huanghaiquan
*
* @param <T>
*/
public abstract class AbstractLedgerOperationHandle<T extends Operation> implements OperationHandle {

static {
DataContractRegistry.register(BytesValue.class);
}

private final Class<T> SUPPORTED_OPERATION_TYPE;

public AbstractLedgerOperationHandle(Class<T> supportedOperationType) {
this.SUPPORTED_OPERATION_TYPE = supportedOperationType;
}

@Override
public final boolean support(Class<?> operationType) {
return SUPPORTED_OPERATION_TYPE.isAssignableFrom(operationType);
}

@Override
public final BytesValue process(Operation op, LedgerDataset newBlockDataset,
TransactionRequestExtension requestContext, LedgerDataset previousBlockDataset,
OperationHandleContext handleContext, LedgerService ledgerService) {
// 权限校验;
SecurityPolicy securityPolicy = SecurityContext.getContextUsersPolicy();
securityPolicy.checkEndpoints(TransactionPermission.DIRECT_OPERATION, MultiIdsPolicy.AT_LEAST_ONE);

// 操作账本;
@SuppressWarnings("unchecked")
T concretedOp = (T) op;
doProcess(concretedOp, newBlockDataset, requestContext, previousBlockDataset, handleContext, ledgerService);

// 账本操作没有返回值;
return null;
}

/**
* @param op
* @param newBlockDataset
* @param requestContext
* @param previousBlockDataset
* @param handleContext
* @param ledgerService
*/
protected abstract void doProcess(T op, LedgerDataset newBlockDataset, TransactionRequestExtension requestContext,
LedgerDataset previousBlockDataset, OperationHandleContext handleContext, LedgerService ledgerService);
}

+ 22
- 7
source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/AbtractContractEventHandle.java View File

@@ -8,14 +8,18 @@ import com.jd.blockchain.ledger.BytesValue;
import com.jd.blockchain.ledger.ContractEventSendOperation;
import com.jd.blockchain.ledger.LedgerException;
import com.jd.blockchain.ledger.Operation;
import com.jd.blockchain.ledger.TransactionPermission;
import com.jd.blockchain.ledger.core.ContractAccount;
import com.jd.blockchain.ledger.core.ContractAccountSet;
import com.jd.blockchain.ledger.core.LedgerDataset;
import com.jd.blockchain.ledger.core.LedgerQueryService;
import com.jd.blockchain.ledger.core.LedgerService;
import com.jd.blockchain.ledger.core.MultiIdsPolicy;
import com.jd.blockchain.ledger.core.OperationHandle;
import com.jd.blockchain.ledger.core.OperationHandleContext;
import com.jd.blockchain.ledger.core.TransactionRequestContext;
import com.jd.blockchain.ledger.core.SecurityContext;
import com.jd.blockchain.ledger.core.SecurityPolicy;
import com.jd.blockchain.ledger.core.TransactionRequestExtension;

@Service
public abstract class AbtractContractEventHandle implements OperationHandle {
@@ -26,9 +30,22 @@ public abstract class AbtractContractEventHandle implements OperationHandle {
}

@Override
public BytesValue process(Operation op, LedgerDataset dataset, TransactionRequestContext requestContext,
public BytesValue process(Operation op, LedgerDataset newBlockDataset, TransactionRequestExtension requestContext,
LedgerDataset previousBlockDataset, OperationHandleContext opHandleContext, LedgerService ledgerService) {
// 权限校验;
SecurityPolicy securityPolicy = SecurityContext.getContextUsersPolicy();
securityPolicy.checkEndpoints(TransactionPermission.CONTRACT_OPERATION, MultiIdsPolicy.AT_LEAST_ONE);

// 操作账本;
ContractEventSendOperation contractOP = (ContractEventSendOperation) op;

return doProcess(requestContext, contractOP, newBlockDataset, previousBlockDataset, opHandleContext,
ledgerService);
}

private BytesValue doProcess(TransactionRequestExtension request, ContractEventSendOperation contractOP,
LedgerDataset newBlockDataset, LedgerDataset previousBlockDataset, OperationHandleContext opHandleContext,
LedgerService ledgerService) {
// 先从账本校验合约的有效性;
// 注意:必须在前一个区块的数据集中进行校验,因为那是经过共识的数据;从当前新区块链数据集校验则会带来攻击风险:未经共识的合约得到执行;
ContractAccountSet contractSet = previousBlockDataset.getContractAccountset();
@@ -50,19 +67,17 @@ public abstract class AbtractContractEventHandle implements OperationHandle {

// 创建合约上下文;
LocalContractEventContext localContractEventContext = new LocalContractEventContext(
requestContext.getRequest().getTransactionContent().getLedgerHash(), contractOP.getEvent());
localContractEventContext.setArgs(contractOP.getArgs()).setTransactionRequest(requestContext.getRequest())
request.getTransactionContent().getLedgerHash(), contractOP.getEvent());
localContractEventContext.setArgs(contractOP.getArgs()).setTransactionRequest(request)
.setLedgerContext(ledgerContext);

// 装载合约;
ContractCode contractCode = loadContractCode(contract);

// 处理合约事件;
return contractCode.processEvent(localContractEventContext);
}
protected abstract ContractCode loadContractCode(ContractAccount contract);

protected abstract ContractCode loadContractCode(ContractAccount contract);

}

+ 20
- 25
source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/ContractCodeDeployOperationHandle.java View File

@@ -1,41 +1,36 @@
package com.jd.blockchain.ledger.core.handles;

import org.springframework.stereotype.Service;

import com.jd.blockchain.ledger.BytesValue;
import com.jd.blockchain.ledger.ContractCodeDeployOperation;
import com.jd.blockchain.ledger.Operation;
import com.jd.blockchain.ledger.LedgerPermission;
import com.jd.blockchain.ledger.core.LedgerDataset;
import com.jd.blockchain.ledger.core.LedgerService;
import com.jd.blockchain.ledger.core.OperationHandle;
import com.jd.blockchain.ledger.core.MultiIdsPolicy;
import com.jd.blockchain.ledger.core.OperationHandleContext;
import com.jd.blockchain.ledger.core.TransactionRequestContext;
import com.jd.blockchain.ledger.core.SecurityContext;
import com.jd.blockchain.ledger.core.SecurityPolicy;
import com.jd.blockchain.ledger.core.TransactionRequestExtension;

@Service
public class ContractCodeDeployOperationHandle implements OperationHandle {
public class ContractCodeDeployOperationHandle extends AbstractLedgerOperationHandle<ContractCodeDeployOperation> {
public ContractCodeDeployOperationHandle() {
super(ContractCodeDeployOperation.class);
}

@Override
public BytesValue process(Operation op, LedgerDataset dataset, TransactionRequestContext requestContext,
LedgerDataset previousBlockDataset, OperationHandleContext handleContext, LedgerService ledgerService) {
ContractCodeDeployOperation contractOP = (ContractCodeDeployOperation) op;
protected void doProcess(ContractCodeDeployOperation op, LedgerDataset newBlockDataset,
TransactionRequestExtension requestContext, LedgerDataset previousBlockDataset,
OperationHandleContext handleContext, LedgerService ledgerService) {
// TODO: 校验合约代码的正确性;
// TODO: 请求者应该提供合约账户的公钥签名,已确定注册的地址的唯一性;

dataset.getContractAccountset().deploy(contractOP.getContractID().getAddress(),
contractOP.getContractID().getPubKey(), contractOP.getAddressSignature(), contractOP.getChainCode());
// TODO: 请求者应该提供合约账户的公钥签名,以确保注册人对注册的地址和公钥具有合法的使用权;

return null;
}
// 权限校验;
SecurityPolicy securityPolicy = SecurityContext.getContextUsersPolicy();
securityPolicy.checkEndpoints(LedgerPermission.UPGRADE_CONTRACT, MultiIdsPolicy.AT_LEAST_ONE);

// @Override
// public AsyncFuture<byte[]> asyncProcess(Operation op, LedgerDataSet newBlockDataset, TransactionRequestContext requestContext, LedgerDataSet previousBlockDataset, OperationHandleContext handleContext, LedgerService ledgerService) {
// return null;
// }

@Override
public boolean support(Class<?> operationType) {
return ContractCodeDeployOperation.class.isAssignableFrom(operationType);
// 操作账本;
ContractCodeDeployOperation contractOP = (ContractCodeDeployOperation) op;
newBlockDataset.getContractAccountset().deploy(contractOP.getContractID().getAddress(),
contractOP.getContractID().getPubKey(), contractOP.getAddressSignature(), contractOP.getChainCode());
}

}

+ 17
- 25
source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/DataAccountKVSetOperationHandle.java View File

@@ -1,32 +1,34 @@
package com.jd.blockchain.ledger.core.handles;

import org.springframework.stereotype.Service;

import com.jd.blockchain.binaryproto.DataContractRegistry;
import com.jd.blockchain.ledger.BytesValue;
import com.jd.blockchain.ledger.DataAccountDoesNotExistException;
import com.jd.blockchain.ledger.DataAccountKVSetOperation;
import com.jd.blockchain.ledger.DataAccountKVSetOperation.KVWriteEntry;
import com.jd.blockchain.ledger.Operation;
import com.jd.blockchain.ledger.LedgerPermission;
import com.jd.blockchain.ledger.core.DataAccount;
import com.jd.blockchain.ledger.core.LedgerDataset;
import com.jd.blockchain.ledger.core.LedgerService;
import com.jd.blockchain.ledger.core.OperationHandle;
import com.jd.blockchain.ledger.core.MultiIdsPolicy;
import com.jd.blockchain.ledger.core.OperationHandleContext;
import com.jd.blockchain.ledger.core.TransactionRequestContext;
import com.jd.blockchain.ledger.core.SecurityContext;
import com.jd.blockchain.ledger.core.SecurityPolicy;
import com.jd.blockchain.ledger.core.TransactionRequestExtension;
import com.jd.blockchain.utils.Bytes;

@Service
public class DataAccountKVSetOperationHandle implements OperationHandle {
static {
DataContractRegistry.register(BytesValue.class);
public class DataAccountKVSetOperationHandle extends AbstractLedgerOperationHandle<DataAccountKVSetOperation> {
public DataAccountKVSetOperationHandle() {
super(DataAccountKVSetOperation.class);
}

@Override
public BytesValue process(Operation op, LedgerDataset dataset, TransactionRequestContext requestContext,
LedgerDataset previousBlockDataset, OperationHandleContext handleContext, LedgerService ledgerService) {
DataAccountKVSetOperation kvWriteOp = (DataAccountKVSetOperation) op;
DataAccount account = dataset.getDataAccountSet().getDataAccount(kvWriteOp.getAccountAddress());
protected void doProcess(DataAccountKVSetOperation kvWriteOp, LedgerDataset newBlockDataset,
TransactionRequestExtension requestContext, LedgerDataset previousBlockDataset,
OperationHandleContext handleContext, LedgerService ledgerService) {
// 权限校验;
SecurityPolicy securityPolicy = SecurityContext.getContextUsersPolicy();
securityPolicy.checkEndpoints(LedgerPermission.WRITE_DATA_ACCOUNT, MultiIdsPolicy.AT_LEAST_ONE);

// 操作账本;
DataAccount account = newBlockDataset.getDataAccountSet().getDataAccount(kvWriteOp.getAccountAddress());
if (account == null) {
throw new DataAccountDoesNotExistException("DataAccount doesn't exist!");
}
@@ -34,17 +36,7 @@ public class DataAccountKVSetOperationHandle implements OperationHandle {
for (KVWriteEntry kvw : writeSet) {
account.setBytes(Bytes.fromString(kvw.getKey()), kvw.getValue(), kvw.getExpectedVersion());
}
return null;
}

// @Override
// public AsyncFuture<byte[]> asyncProcess(Operation op, LedgerDataSet newBlockDataset, TransactionRequestContext requestContext, LedgerDataSet previousBlockDataset, OperationHandleContext handleContext, LedgerService ledgerService) {
// return null;
// }

@Override
public boolean support(Class<?> operationType) {
return DataAccountKVSetOperation.class.isAssignableFrom(operationType);
}

}

+ 21
- 28
source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/DataAccountRegisterOperationHandle.java View File

@@ -1,42 +1,35 @@
package com.jd.blockchain.ledger.core.handles;

import org.springframework.stereotype.Service;

import com.jd.blockchain.ledger.BlockchainIdentity;
import com.jd.blockchain.ledger.BytesValue;
import com.jd.blockchain.ledger.DataAccountRegisterOperation;
import com.jd.blockchain.ledger.Operation;
import com.jd.blockchain.ledger.LedgerPermission;
import com.jd.blockchain.ledger.core.LedgerDataset;
import com.jd.blockchain.ledger.core.LedgerService;
import com.jd.blockchain.ledger.core.OperationHandle;
import com.jd.blockchain.ledger.core.MultiIdsPolicy;
import com.jd.blockchain.ledger.core.OperationHandleContext;
import com.jd.blockchain.ledger.core.TransactionRequestContext;

@Service
public class DataAccountRegisterOperationHandle implements OperationHandle {

@Override
public BytesValue process(Operation op, LedgerDataset dataset, TransactionRequestContext requestContext,
LedgerDataset previousBlockDataset, OperationHandleContext handleContext, LedgerService ledgerService) {
DataAccountRegisterOperation dataAccountRegOp = (DataAccountRegisterOperation) op;
BlockchainIdentity bid = dataAccountRegOp.getAccountID();
import com.jd.blockchain.ledger.core.SecurityContext;
import com.jd.blockchain.ledger.core.SecurityPolicy;
import com.jd.blockchain.ledger.core.TransactionRequestExtension;

//TODO: 校验用户身份;

//TODO: 请求者应该提供数据账户的公钥签名,已确定注册的地址的唯一性;
dataset.getDataAccountSet().register(bid.getAddress(), bid.getPubKey(), null);

return null;
public class DataAccountRegisterOperationHandle extends AbstractLedgerOperationHandle<DataAccountRegisterOperation> {
public DataAccountRegisterOperationHandle() {
super(DataAccountRegisterOperation.class);
}
@Override
protected void doProcess(DataAccountRegisterOperation op, LedgerDataset newBlockDataset,
TransactionRequestExtension requestContext, LedgerDataset previousBlockDataset,
OperationHandleContext handleContext, LedgerService ledgerService) {
// TODO: 请求者应该提供数据账户的公钥签名,以更好地确保注册人对该地址和公钥具有合法使用权;

// @Override
// public AsyncFuture<byte[]> asyncProcess(Operation op, LedgerDataSet newBlockDataset, TransactionRequestContext requestContext, LedgerDataSet previousBlockDataset, OperationHandleContext handleContext, LedgerService ledgerService) {
// return null;
// }
// 权限校验;
SecurityPolicy securityPolicy = SecurityContext.getContextUsersPolicy();
securityPolicy.checkEndpoints(LedgerPermission.REGISTER_DATA_ACCOUNT, MultiIdsPolicy.AT_LEAST_ONE);

@Override
public boolean support(Class<?> operationType) {
return DataAccountRegisterOperation.class.isAssignableFrom(operationType);
// 操作账本;
DataAccountRegisterOperation dataAccountRegOp = (DataAccountRegisterOperation) op;
BlockchainIdentity bid = dataAccountRegOp.getAccountID();
newBlockDataset.getDataAccountSet().register(bid.getAddress(), bid.getPubKey(), null);
}

}

+ 0
- 8
source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/JVMContractEventSendOperationHandle.java View File

@@ -26,12 +26,4 @@ public class JVMContractEventSendOperationHandle extends AbtractContractEventHan
return contractCode;
}

// @Override
// public AsyncFuture<byte[]> asyncProcess(Operation op, LedgerDataSet newBlockDataset,
// TransactionRequestContext requestContext, LedgerDataSet previousBlockDataset,
// OperationHandleContext handleContext, LedgerService ledgerService) {
// // TODO Auto-generated method stub
// return null;
// }

}

+ 18
- 18
source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/handles/UserRegisterOperationHandle.java View File

@@ -1,37 +1,37 @@
package com.jd.blockchain.ledger.core.handles;

import com.jd.blockchain.ledger.BlockchainIdentity;
import com.jd.blockchain.ledger.BytesValue;
import com.jd.blockchain.ledger.Operation;
import com.jd.blockchain.ledger.LedgerPermission;
import com.jd.blockchain.ledger.UserRegisterOperation;
import com.jd.blockchain.ledger.core.LedgerDataset;
import com.jd.blockchain.ledger.core.LedgerService;
import com.jd.blockchain.ledger.core.OperationHandle;
import com.jd.blockchain.ledger.core.MultiIdsPolicy;
import com.jd.blockchain.ledger.core.OperationHandleContext;
import com.jd.blockchain.ledger.core.TransactionRequestContext;
import com.jd.blockchain.ledger.core.SecurityContext;
import com.jd.blockchain.ledger.core.SecurityPolicy;
import com.jd.blockchain.ledger.core.TransactionRequestExtension;
import com.jd.blockchain.utils.Bytes;


public class UserRegisterOperationHandle implements OperationHandle {
public class UserRegisterOperationHandle extends AbstractLedgerOperationHandle<UserRegisterOperation> {
public UserRegisterOperationHandle() {
super(UserRegisterOperation.class);
}

@Override
public BytesValue process(Operation op, LedgerDataset dataset, TransactionRequestContext requestContext,
LedgerDataset previousBlockDataset, OperationHandleContext handleContext, LedgerService ledgerService) {


protected void doProcess(UserRegisterOperation op, LedgerDataset newBlockDataset,
TransactionRequestExtension requestContext, LedgerDataset previousBlockDataset,
OperationHandleContext handleContext, LedgerService ledgerService) {
// 权限校验;
SecurityPolicy securityPolicy = SecurityContext.getContextUsersPolicy();
securityPolicy.checkEndpoints(LedgerPermission.REGISTER_USER, MultiIdsPolicy.AT_LEAST_ONE);

// 操作账本;
UserRegisterOperation userRegOp = (UserRegisterOperation) op;
BlockchainIdentity bid = userRegOp.getUserID();

Bytes userAddress = bid.getAddress();

dataset.getUserAccountSet().register(userAddress, bid.getPubKey());

return null;
}

@Override
public boolean support(Class<?> operationType) {
return UserRegisterOperation.class.isAssignableFrom(operationType);
newBlockDataset.getUserAccountSet().register(userAddress, bid.getPubKey());
}

}

+ 22
- 7
source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/ContractInvokingTest.java View File

@@ -15,6 +15,7 @@ import org.mockito.Mockito;
import java.util.Random;

import static org.junit.Assert.*;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyLong;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.*;
@@ -65,15 +66,15 @@ public class ContractInvokingTest {
// 发布指定地址合约
deploy(ledgerRepo, ledgerManager, opReg, ledgerHash, contractKey);


// 创建新区块的交易处理器;
LedgerBlock preBlock = ledgerRepo.getLatestBlock();
LedgerDataset previousBlockDataset = ledgerRepo.getDataSet(preBlock);

// 加载合约
LedgerEditor newBlockEditor = ledgerRepo.createNextBlock();
TransactionBatchProcessor txbatchProcessor = new TransactionBatchProcessor(newBlockEditor, previousBlockDataset,
opReg, ledgerManager);
LedgerSecurityManager securityManager = getSecurityManager();
TransactionBatchProcessor txbatchProcessor = new TransactionBatchProcessor(securityManager, newBlockEditor,
previousBlockDataset, opReg, ledgerManager);

// 构建基于接口调用合约的交易请求,用于测试合约调用;
TxBuilder txBuilder = new TxBuilder(ledgerHash);
@@ -119,16 +120,16 @@ public class ContractInvokingTest {
}

private void deploy(LedgerRepository ledgerRepo, LedgerManager ledgerManager,
DefaultOperationHandleRegisteration opReg, HashDigest ledgerHash,
BlockchainKeypair contractKey) {
DefaultOperationHandleRegisteration opReg, HashDigest ledgerHash, BlockchainKeypair contractKey) {
// 创建新区块的交易处理器;
LedgerBlock preBlock = ledgerRepo.getLatestBlock();
LedgerDataset previousBlockDataset = ledgerRepo.getDataSet(preBlock);

// 加载合约
LedgerEditor newBlockEditor = ledgerRepo.createNextBlock();
TransactionBatchProcessor txbatchProcessor = new TransactionBatchProcessor(newBlockEditor, previousBlockDataset,
opReg, ledgerManager);
LedgerSecurityManager securityManager = getSecurityManager();
TransactionBatchProcessor txbatchProcessor = new TransactionBatchProcessor(securityManager, newBlockEditor,
previousBlockDataset, opReg, ledgerManager);

// 构建基于接口调用合约的交易请求,用于测试合约调用;
TxBuilder txBuilder = new TxBuilder(ledgerHash);
@@ -189,4 +190,18 @@ public class ContractInvokingTest {
new Random().nextBytes(chainCode);
return chainCode;
}

private static LedgerSecurityManager getSecurityManager() {
LedgerSecurityManager securityManager = Mockito.mock(LedgerSecurityManager.class);

SecurityPolicy securityPolicy = Mockito.mock(SecurityPolicy.class);
when(securityPolicy.isEnableToEndpoints(any(LedgerPermission.class), any())).thenReturn(true);
when(securityPolicy.isEnableToEndpoints(any(TransactionPermission.class), any())).thenReturn(true);
when(securityPolicy.isEnableToNodes(any(LedgerPermission.class), any())).thenReturn(true);
when(securityPolicy.isEnableToNodes(any(TransactionPermission.class), any())).thenReturn(true);

when(securityManager.getSecurityPolicy(any(), any())).thenReturn(securityPolicy);

return securityManager;
}
}

+ 141
- 0
source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/LedgerSecurityManagerTest.java View File

@@ -0,0 +1,141 @@
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 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.Privileges;
import com.jd.blockchain.ledger.RolePrivilegeSettings;
import com.jd.blockchain.ledger.RolesPolicy;
import com.jd.blockchain.ledger.TransactionPermission;
import com.jd.blockchain.ledger.UserRoleSettings;
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.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 RolePrivilegeSettings initRoles(MemoryKVStorage testStorage, String[] roles, Privileges[] privilege) {
String prefix = "role-privilege/";
RolePrivilegeDataset rolePrivilegeDataset = new RolePrivilegeDataset(CRYPTO_SETTINGS, prefix, testStorage,
testStorage);
for (int i = 0; i < roles.length; i++) {
rolePrivilegeDataset.addRolePrivilege(roles[i], privilege[i]);
}

rolePrivilegeDataset.commit();

return rolePrivilegeDataset;
}

private UserRoleSettings initUserRoless(MemoryKVStorage testStorage, Bytes[] userAddresses, RolesPolicy[] policies,
String[][] roles) {
String prefix = "user-roles/";
UserRoleDataset userRolesDataset = new UserRoleDataset(CRYPTO_SETTINGS, prefix, testStorage, testStorage);

for (int i = 0; i < userAddresses.length; i++) {
userRolesDataset.addUserRoles(userAddresses[i], policies[i], roles[i]);
}

userRolesDataset.commit();

return userRolesDataset;
}

@Test
public void testGetSecurityPolicy() {
MemoryKVStorage testStorage = new MemoryKVStorage();

final BlockchainKeypair kpManager = BlockchainKeyGenerator.getInstance().generate();
final BlockchainKeypair kpEmployee = BlockchainKeyGenerator.getInstance().generate();
final BlockchainKeypair kpDevoice = BlockchainKeyGenerator.getInstance().generate();
final Map<Bytes, BlockchainKeypair> endpoints = new HashMap<>();
endpoints.put(kpManager.getAddress(), kpManager);
endpoints.put(kpEmployee.getAddress(), kpEmployee);
final Map<Bytes, BlockchainKeypair> nodes = new HashMap<>();
nodes.put(kpDevoice.getAddress(), kpDevoice);

final String ROLE_ADMIN = "ID_ADMIN";
final String ROLE_OPERATOR = "OPERATOR";
final String ROLE_DATA_COLLECTOR = "DATA_COLLECTOR";

final Privileges PRIVILEGES_ADMIN = Privileges.configure()
.enable(LedgerPermission.REGISTER_USER, LedgerPermission.REGISTER_DATA_ACCOUNT)
.enable(TransactionPermission.DIRECT_OPERATION, TransactionPermission.CONTRACT_OPERATION);

final Privileges PRIVILEGES_OPERATOR = Privileges.configure()
.enable(LedgerPermission.WRITE_DATA_ACCOUNT, LedgerPermission.APPROVE_TX)
.enable(TransactionPermission.CONTRACT_OPERATION);

final Privileges PRIVILEGES_DATA_COLLECTOR = Privileges.configure().enable(LedgerPermission.WRITE_DATA_ACCOUNT)
.enable(TransactionPermission.CONTRACT_OPERATION);

RolePrivilegeSettings rolePrivilegeSettings = initRoles(testStorage,
new String[] { ROLE_ADMIN, ROLE_OPERATOR, ROLE_DATA_COLLECTOR },
new Privileges[] { PRIVILEGES_ADMIN, PRIVILEGES_OPERATOR, PRIVILEGES_DATA_COLLECTOR });

String[] managerRoles = new String[] { ROLE_ADMIN, ROLE_OPERATOR };
String[] employeeRoles = new String[] { ROLE_OPERATOR };
String[] devoiceRoles = new String[] { ROLE_DATA_COLLECTOR };
UserRoleSettings userRolesSettings = initUserRoless(testStorage,
new Bytes[] { kpManager.getAddress(), kpEmployee.getAddress(), kpDevoice.getAddress() },
new RolesPolicy[] { RolesPolicy.UNION, RolesPolicy.UNION, RolesPolicy.UNION },
new String[][] { managerRoles, employeeRoles, devoiceRoles });
LedgerSecurityManager securityManager = new LedgerSecurityManagerImpl(rolePrivilegeSettings, userRolesSettings);
SecurityPolicy policy = securityManager.getSecurityPolicy(endpoints.keySet(), nodes.keySet());
assertTrue(policy.isEnableToEndpoints(LedgerPermission.REGISTER_USER, MultiIdsPolicy.AT_LEAST_ONE));
assertTrue(policy.isEnableToEndpoints(LedgerPermission.REGISTER_DATA_ACCOUNT, MultiIdsPolicy.AT_LEAST_ONE));
assertTrue(policy.isEnableToEndpoints(LedgerPermission.WRITE_DATA_ACCOUNT, MultiIdsPolicy.AT_LEAST_ONE));
assertTrue(policy.isEnableToEndpoints(LedgerPermission.APPROVE_TX, MultiIdsPolicy.AT_LEAST_ONE));
assertFalse(policy.isEnableToEndpoints(LedgerPermission.REGISTER_USER, MultiIdsPolicy.ALL));
assertFalse(policy.isEnableToEndpoints(LedgerPermission.AUTHORIZE_ROLES, MultiIdsPolicy.AT_LEAST_ONE));
}

}

+ 43
- 14
source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/TransactionBatchProcessorTest.java View File

@@ -5,8 +5,11 @@ 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 static org.mockito.Matchers.any;
import static org.mockito.Mockito.when;

import org.junit.Test;
import org.mockito.Mockito;

import com.jd.blockchain.binaryproto.DataContractRegistry;
import com.jd.blockchain.crypto.HashDigest;
@@ -17,10 +20,12 @@ import com.jd.blockchain.ledger.DataAccountRegisterOperation;
import com.jd.blockchain.ledger.EndpointRequest;
import com.jd.blockchain.ledger.LedgerBlock;
import com.jd.blockchain.ledger.LedgerInitSetting;
import com.jd.blockchain.ledger.LedgerPermission;
import com.jd.blockchain.ledger.LedgerTransaction;
import com.jd.blockchain.ledger.NodeRequest;
import com.jd.blockchain.ledger.TransactionContent;
import com.jd.blockchain.ledger.TransactionContentBody;
import com.jd.blockchain.ledger.TransactionPermission;
import com.jd.blockchain.ledger.TransactionRequest;
import com.jd.blockchain.ledger.TransactionResponse;
import com.jd.blockchain.ledger.TransactionState;
@@ -31,9 +36,11 @@ import com.jd.blockchain.ledger.core.LedgerDataset;
import com.jd.blockchain.ledger.core.LedgerEditor;
import com.jd.blockchain.ledger.core.LedgerManager;
import com.jd.blockchain.ledger.core.LedgerRepository;
import com.jd.blockchain.ledger.core.LedgerSecurityManager;
import com.jd.blockchain.ledger.core.LedgerTransactionContext;
import com.jd.blockchain.ledger.core.LedgerTransactionalEditor;
import com.jd.blockchain.ledger.core.OperationHandleRegisteration;
import com.jd.blockchain.ledger.core.SecurityPolicy;
import com.jd.blockchain.ledger.core.TransactionBatchProcessor;
import com.jd.blockchain.ledger.core.UserAccount;
import com.jd.blockchain.storage.service.utils.MemoryKVStorage;
@@ -85,8 +92,9 @@ public class TransactionBatchProcessorTest {
LedgerEditor newBlockEditor = ledgerRepo.createNextBlock();

OperationHandleRegisteration opReg = new DefaultOperationHandleRegisteration();
TransactionBatchProcessor txbatchProcessor = new TransactionBatchProcessor(newBlockEditor, previousBlockDataset,
opReg, ledgerManager);
LedgerSecurityManager securityManager = getSecurityManager();
TransactionBatchProcessor txbatchProcessor = new TransactionBatchProcessor(securityManager, newBlockEditor,
previousBlockDataset, opReg, ledgerManager);

// 注册新用户;
BlockchainKeypair userKeypair = BlockchainKeyGenerator.getInstance().generate();
@@ -108,6 +116,20 @@ public class TransactionBatchProcessorTest {
assertEquals(TransactionState.SUCCESS, txResp.getExecutionState());
}

private static LedgerSecurityManager getSecurityManager() {
LedgerSecurityManager securityManager = Mockito.mock(LedgerSecurityManager.class);

SecurityPolicy securityPolicy = Mockito.mock(SecurityPolicy.class);
when(securityPolicy.isEnableToEndpoints(any(LedgerPermission.class), any())).thenReturn(true);
when(securityPolicy.isEnableToEndpoints(any(TransactionPermission.class), any())).thenReturn(true);
when(securityPolicy.isEnableToNodes(any(LedgerPermission.class), any())).thenReturn(true);
when(securityPolicy.isEnableToNodes(any(TransactionPermission.class), any())).thenReturn(true);

when(securityManager.getSecurityPolicy(any(), any())).thenReturn(securityPolicy);

return securityManager;
}

@Test
public void testMultiTxsProcess() {
final MemoryKVStorage STORAGE = new MemoryKVStorage();
@@ -130,8 +152,9 @@ public class TransactionBatchProcessorTest {
LedgerEditor newBlockEditor = ledgerRepo.createNextBlock();

OperationHandleRegisteration opReg = new DefaultOperationHandleRegisteration();
TransactionBatchProcessor txbatchProcessor = new TransactionBatchProcessor(newBlockEditor, previousBlockDataset,
opReg, ledgerManager);
LedgerSecurityManager securityManager = getSecurityManager();
TransactionBatchProcessor txbatchProcessor = new TransactionBatchProcessor(securityManager, newBlockEditor,
previousBlockDataset, opReg, ledgerManager);

// 注册新用户;
BlockchainKeypair userKeypair1 = BlockchainKeyGenerator.getInstance().generate();
@@ -187,8 +210,9 @@ public class TransactionBatchProcessorTest {
LedgerEditor newBlockEditor = ledgerRepo.createNextBlock();

OperationHandleRegisteration opReg = new DefaultOperationHandleRegisteration();
TransactionBatchProcessor txbatchProcessor = new TransactionBatchProcessor(newBlockEditor, previousBlockDataset,
opReg, ledgerManager);
LedgerSecurityManager securityManager = getSecurityManager();
TransactionBatchProcessor txbatchProcessor = new TransactionBatchProcessor(securityManager, newBlockEditor,
previousBlockDataset, opReg, ledgerManager);

// 注册新用户;
BlockchainKeypair userKeypair1 = BlockchainKeyGenerator.getInstance().generate();
@@ -267,8 +291,9 @@ public class TransactionBatchProcessorTest {
LedgerEditor newBlockEditor = ledgerRepo.createNextBlock();

OperationHandleRegisteration opReg = new DefaultOperationHandleRegisteration();
TransactionBatchProcessor txbatchProcessor = new TransactionBatchProcessor(newBlockEditor, previousBlockDataset,
opReg, ledgerManager);
LedgerSecurityManager securityManager = getSecurityManager();
TransactionBatchProcessor txbatchProcessor = new TransactionBatchProcessor(securityManager, newBlockEditor,
previousBlockDataset, opReg, ledgerManager);

BlockchainKeypair dataAccountKeypair = BlockchainKeyGenerator.getInstance().generate();
TransactionRequest transactionRequest1 = LedgerTestUtils.createTxRequest_DataAccountReg(dataAccountKeypair,
@@ -293,7 +318,8 @@ public class TransactionBatchProcessorTest {

newBlockEditor = ledgerRepo.createNextBlock();
previousBlockDataset = ledgerRepo.getDataSet(ledgerRepo.getLatestBlock());
txbatchProcessor = new TransactionBatchProcessor(newBlockEditor, previousBlockDataset, opReg, ledgerManager);
txbatchProcessor = new TransactionBatchProcessor(securityManager, newBlockEditor, previousBlockDataset, opReg,
ledgerManager);

txbatchProcessor.schedule(txreq1);
txbatchProcessor.schedule(txreq2);
@@ -316,7 +342,7 @@ public class TransactionBatchProcessorTest {
assertNotNull(v1_1);
assertNotNull(v2);
assertNotNull(v3);
assertEquals("V-1-1", v1_0.getValue().toUTF8String());
assertEquals("V-1-2", v1_1.getValue().toUTF8String());
assertEquals("V-2-1", v2.getValue().toUTF8String());
@@ -332,7 +358,8 @@ public class TransactionBatchProcessorTest {

newBlockEditor = ledgerRepo.createNextBlock();
previousBlockDataset = ledgerRepo.getDataSet(ledgerRepo.getLatestBlock());
txbatchProcessor = new TransactionBatchProcessor(newBlockEditor, previousBlockDataset, opReg, ledgerManager);
txbatchProcessor = new TransactionBatchProcessor(securityManager, newBlockEditor, previousBlockDataset, opReg,
ledgerManager);

txbatchProcessor.schedule(txreq5);
txbatchProcessor.schedule(txreq6);
@@ -343,11 +370,13 @@ public class TransactionBatchProcessorTest {
BytesValue v1 = ledgerRepo.getDataAccountSet().getDataAccount(dataAccountKeypair.getAddress()).getBytes("K1");
v3 = ledgerRepo.getDataAccountSet().getDataAccount(dataAccountKeypair.getAddress()).getBytes("K3");

long k1_version = ledgerRepo.getDataAccountSet().getDataAccount(dataAccountKeypair.getAddress()).getDataVersion("K1");
long k1_version = ledgerRepo.getDataAccountSet().getDataAccount(dataAccountKeypair.getAddress())
.getDataVersion("K1");
assertEquals(1, k1_version);
long k3_version = ledgerRepo.getDataAccountSet().getDataAccount(dataAccountKeypair.getAddress()).getDataVersion("K3");
long k3_version = ledgerRepo.getDataAccountSet().getDataAccount(dataAccountKeypair.getAddress())
.getDataVersion("K3");
assertEquals(1, k3_version);
assertNotNull(v1);
assertNotNull(v3);
assertEquals("V-1-2", v1.getValue().toUTF8String());


+ 0
- 58
source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/AbstractPrivilege.java View File

@@ -1,58 +0,0 @@
package com.jd.blockchain.ledger;

import java.util.BitSet;

import com.jd.blockchain.utils.io.BytesSerializable;

/**
* LedgerPrivilege 账本特权是授权给特定角色的权限代码序列;
*
* @author huanghaiquan
*
*/
public abstract class AbstractPrivilege<E extends Enum<?>> implements Privilege<E>, BytesSerializable {

private BitSet permissionBits;
public AbstractPrivilege() {
permissionBits = new BitSet();
}

public AbstractPrivilege(byte[] codeBytes) {
permissionBits = BitSet.valueOf(codeBytes);
}

public boolean isEnable(E permission) {
return permissionBits.get(getCodeIndex(permission));
}

public void enable(E permission) {
permissionBits.set(getCodeIndex(permission));
}

public void disable(E permission) {
permissionBits.clear(getCodeIndex(permission));
}
@SuppressWarnings("unchecked")
public void enable(E... permissions) {
for (E p : permissions) {
permissionBits.set(getCodeIndex(p));
}
}
@SuppressWarnings("unchecked")
public void disable(E... permissions) {
for (E p : permissions) {
permissionBits.clear(getCodeIndex(p));
}
}

protected abstract int getCodeIndex(E permission);

@Override
public byte[] toBytes() {
return permissionBits.toByteArray();
}

}

+ 13
- 7
source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/LedgerPrivilege.java View File

@@ -6,18 +6,24 @@ package com.jd.blockchain.ledger;
* @author huanghaiquan
*
*/
public class LedgerPrivilege extends AbstractPrivilege<LedgerPermission> {
public class LedgerPrivilege extends PrivilegeBitset<LedgerPermission> {

private static final CodeIndexer<LedgerPermission> CODE_INDEXER = new LedgerPermissionCodeIndexer();

public LedgerPrivilege() {
super(CODE_INDEXER);
}
public LedgerPrivilege(byte[] codeBytes) {
super(codeBytes);
super(codeBytes, CODE_INDEXER);
}

@Override
protected int getCodeIndex(LedgerPermission permission) {
return permission.CODE & 0xFF;
}
private static class LedgerPermissionCodeIndexer implements CodeIndexer<LedgerPermission> {

@Override
public int getCodeIndex(LedgerPermission permission) {
return permission.CODE & 0xFF;
}

}
}

+ 17
- 0
source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/LedgerSecurityException.java View File

@@ -0,0 +1,17 @@
package com.jd.blockchain.ledger;

public class LedgerSecurityException extends RuntimeException {

private static final long serialVersionUID = -4090881296855827888L;

public LedgerSecurityException(String message) {
super(message);
}

public LedgerSecurityException(String message, Throwable cause) {
super(message, cause);
}

}

+ 15
- 0
source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ParticipantDoesNotExistException.java View File

@@ -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);
}

}

+ 121
- 0
source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/PrivilegeBitset.java View File

@@ -0,0 +1,121 @@
package com.jd.blockchain.ledger;

import java.util.BitSet;

import com.jd.blockchain.utils.io.BytesSerializable;

/**
* PrivilegeBitset 定义了用位表示的权限码;
*
* @author huanghaiquan
*
*/
public class PrivilegeBitset<E extends Enum<?>> implements Privilege<E>, BytesSerializable {

private BitSet permissionBits;

private CodeIndexer<E> codeIndexer;

public PrivilegeBitset(CodeIndexer<E> codeIndexer) {
this(new BitSet(), codeIndexer);
}

public PrivilegeBitset(byte[] codeBytes, CodeIndexer<E> codeIndexer) {
this(BitSet.valueOf(codeBytes), codeIndexer);
}

private PrivilegeBitset(BitSet bits, CodeIndexer<E> codeIndexer) {
this.permissionBits = bits;
this.codeIndexer = codeIndexer;
}

public boolean isEnable(E permission) {
return permissionBits.get(codeIndexer.getCodeIndex(permission));
}

public void enable(E permission) {
permissionBits.set(codeIndexer.getCodeIndex(permission));
}

public void disable(E permission) {
permissionBits.clear(codeIndexer.getCodeIndex(permission));
}

@SuppressWarnings("unchecked")
public void enable(E... permissions) {
for (E p : permissions) {
permissionBits.set(codeIndexer.getCodeIndex(p));
}
}

@SuppressWarnings("unchecked")
public void disable(E... permissions) {
for (E p : permissions) {
permissionBits.clear(codeIndexer.getCodeIndex(p));
}
}

@Override
public byte[] toBytes() {
return permissionBits.toByteArray();
}

/**
* 把指定的权限合并到当前的权限中; <br>
*
* @param privileges
* @return
*/
public Privilege<E> union(PrivilegeBitset<E>... privileges) {
return union(privileges, 0, privileges.length);
}

/**
* 把指定的权限合并到当前的权限中; <br>
* @param privileges
* @param offset
* @param count
* @return
*/
public Privilege<E> union(PrivilegeBitset<E>[] privileges, int offset, int count) {
BitSet bits = this.permissionBits;
for (int i = 0; i < count; i++) {
bits.or(privileges[i + offset].permissionBits);
}
return this;
}

/**
* 保留当前的权限与指定权限的共同生效的部分,同时清除其它的权限位; <br>
*
* @param privileges
* @return
*/
public Privilege<E> intersect(PrivilegeBitset<E>... privileges) {
return intersect(privileges, 0, privileges.length);
}

/**
* 保留当前的权限与指定权限的共同生效的部分,同时清除其它的权限位; <br>
*
* @param privileges
* @param offset
* @param count
* @return
*/
public Privilege<E> intersect(PrivilegeBitset<E>[] privileges, int offset, int count) {
BitSet bits = this.permissionBits;
for (int i = 0; i < count; i++) {
bits.and(privileges[i + offset].permissionBits);
}
return this;
}

public PrivilegeBitset<E> clone() {
return new PrivilegeBitset<E>((BitSet) permissionBits.clone(), codeIndexer);
}

static interface CodeIndexer<E extends Enum<?>> {
int getCodeIndex(E permission);
}
}

+ 65
- 0
source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/Privileges.java View File

@@ -0,0 +1,65 @@
package com.jd.blockchain.ledger;

public class Privileges implements PrivilegeSet {

private LedgerPrivilege ledgerPrivilege;

private TransactionPrivilege txPrivilege;

protected Privileges() {
this.ledgerPrivilege = new LedgerPrivilege();
this.txPrivilege = new TransactionPrivilege();
}

protected Privileges(PrivilegeSet privilege) {
this.ledgerPrivilege = privilege.getLedgerPrivilege();
this.txPrivilege = privilege.getTransactionPrivilege();
}

protected Privileges(LedgerPrivilege ledgerPrivilege, TransactionPrivilege txPrivilege) {
this.ledgerPrivilege = ledgerPrivilege;
this.txPrivilege = txPrivilege;
}

@Override
public LedgerPrivilege getLedgerPrivilege() {
return ledgerPrivilege;
}

public void setLedgerPrivilege(LedgerPrivilege ledgerPrivilege) {
this.ledgerPrivilege = ledgerPrivilege;
}

@Override
public TransactionPrivilege getTransactionPrivilege() {
return txPrivilege;
}

public void setTransactionPrivilege(TransactionPrivilege txPrivilege) {
this.txPrivilege = txPrivilege;
}

public static Privileges configure() {
return new Privileges();
}
public Privileges enable(LedgerPermission...ledgerPermissions) {
this.ledgerPrivilege.enable(ledgerPermissions);
return this;
}
public Privileges disable(LedgerPermission...ledgerPermissions) {
this.ledgerPrivilege.disable(ledgerPermissions);
return this;
}
public Privileges enable(TransactionPermission...transactionPermissions) {
this.txPrivilege.enable(transactionPermissions);
return this;
}
public Privileges disable(TransactionPermission...transactionPermissions) {
this.txPrivilege.disable(transactionPermissions);
return this;
}
}

+ 11
- 0
source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/RolePrivilegeSettings.java View File

@@ -8,6 +8,17 @@ public interface RolePrivilegeSettings {
public static final int MAX_ROLE_NAME_LENGTH = 20;

long getRoleCount();
/**
* 加入新的角色授权; <br>
*
* 如果指定的角色已经存在,则引发 {@link LedgerException} 异常;
*
* @param roleName 角色名称;不能超过 {@link #MAX_ROLE_NAME_LENGTH} 个 Unicode 字符;
* @param ledgerPrivilege
* @param txPrivilege
*/
long addRolePrivilege(String roleName, Privileges privileges);

/**
* 加入新的角色授权; <br>


+ 5
- 30
source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/RolePrivileges.java View File

@@ -6,35 +6,28 @@ package com.jd.blockchain.ledger;
* @author huanghaiquan
*
*/
public class RolePrivileges implements PrivilegeSet {
public class RolePrivileges extends Privileges {

private String roleName;

private long version;

private LedgerPrivilege ledgerPrivilege;

private TransactionPrivilege txPrivilege;

public RolePrivileges(String roleName, long version) {
this.roleName = roleName;
this.version = version;
this.ledgerPrivilege = new LedgerPrivilege();
this.txPrivilege = new TransactionPrivilege();
}

public RolePrivileges(String roleName, long version, PrivilegeSet privilege) {
super(privilege);
this.roleName = roleName;
this.version = version;
this.ledgerPrivilege = privilege.getLedgerPrivilege();
this.txPrivilege = privilege.getTransactionPrivilege();
}

public RolePrivileges(String roleName, long version, LedgerPrivilege ledgerPrivilege, TransactionPrivilege txPrivilege) {
public RolePrivileges(String roleName, long version, LedgerPrivilege ledgerPrivilege,
TransactionPrivilege txPrivilege) {
super(ledgerPrivilege, txPrivilege);
this.roleName = roleName;
this.version = version;
this.ledgerPrivilege = ledgerPrivilege;
this.txPrivilege = txPrivilege;
}

public String getRoleName() {
@@ -45,22 +38,4 @@ public class RolePrivileges implements PrivilegeSet {
return version;
}

@Override
public LedgerPrivilege getLedgerPrivilege() {
return ledgerPrivilege;
}

public void setLedgerPrivilege(LedgerPrivilege ledgerPrivilege) {
this.ledgerPrivilege = ledgerPrivilege;
}

@Override
public TransactionPrivilege getTransactionPrivilege() {
return txPrivilege;
}

public void setTransactionPrivilege(TransactionPrivilege txPrivilege) {
this.txPrivilege = txPrivilege;
}

}

+ 12
- 6
source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionPrivilege.java View File

@@ -1,17 +1,23 @@
package com.jd.blockchain.ledger;

public class TransactionPrivilege extends AbstractPrivilege<TransactionPermission> {
public class TransactionPrivilege extends PrivilegeBitset<TransactionPermission> {

private static final CodeIndexer<TransactionPermission> CODE_INDEXER = new TransactionPermissionCodeIndexer();

public TransactionPrivilege() {
super(CODE_INDEXER);
}

public TransactionPrivilege(byte[] codeBytes) {
super(codeBytes);
super(codeBytes, CODE_INDEXER);
}

@Override
protected int getCodeIndex(TransactionPermission permission) {
return permission.CODE & 0xFF;
}
private static class TransactionPermissionCodeIndexer implements CodeIndexer<TransactionPermission> {

@Override
public int getCodeIndex(TransactionPermission permission) {
return permission.CODE & 0xFF;
}

}
}

+ 10
- 0
source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionState.java View File

@@ -39,6 +39,16 @@ public enum TransactionState {
*/
CONTRACT_DOES_NOT_EXIST((byte) 0x04),
/**
* 参与方不存在;
*/
PARTICIPANT_DOES_NOT_EXIST((byte) 0x05),
/**
* 被安全策略拒绝;
*/
REJECTED_BY_SECURITY_POLICY((byte) 0x10),
/**
* 由于在错误的账本上执行交易而被丢弃;
*/


+ 9
- 5
source/tools/tools-mocker/src/main/java/com/jd/blockchain/mocker/MockerNodeContext.java View File

@@ -37,6 +37,7 @@ import com.jd.blockchain.ledger.LedgerAdminInfo;
import com.jd.blockchain.ledger.LedgerBlock;
import com.jd.blockchain.ledger.LedgerInfo;
import com.jd.blockchain.ledger.LedgerMetadata;
import com.jd.blockchain.ledger.LedgerPermission;
import com.jd.blockchain.ledger.LedgerTransaction;
import com.jd.blockchain.ledger.NodeRequest;
import com.jd.blockchain.ledger.Operation;
@@ -44,6 +45,7 @@ import com.jd.blockchain.ledger.OperationResult;
import com.jd.blockchain.ledger.ParticipantNode;
import com.jd.blockchain.ledger.TransactionContent;
import com.jd.blockchain.ledger.TransactionContentBody;
import com.jd.blockchain.ledger.TransactionPermission;
import com.jd.blockchain.ledger.TransactionRequest;
import com.jd.blockchain.ledger.TransactionRequestBuilder;
import com.jd.blockchain.ledger.TransactionResponse;
@@ -56,6 +58,8 @@ import com.jd.blockchain.ledger.core.LedgerEditor;
import com.jd.blockchain.ledger.core.LedgerManager;
import com.jd.blockchain.ledger.core.LedgerQueryService;
import com.jd.blockchain.ledger.core.LedgerRepository;
import com.jd.blockchain.ledger.core.LedgerSecurityManager;
import com.jd.blockchain.ledger.core.SecurityPolicy;
import com.jd.blockchain.ledger.core.TransactionBatchProcessor;
import com.jd.blockchain.mocker.config.MockerConstant;
import com.jd.blockchain.mocker.config.PresetAnswerPrompter;
@@ -121,7 +125,7 @@ public class MockerNodeContext implements BlockchainQueryService {
DataContractRegistry.register(ActionResponse.class);
DataContractRegistry.register(ClientIdentifications.class);
DataContractRegistry.register(ClientIdentification.class);
// DataContractRegistry.register(LedgerAdminInfo.class);

ByteArrayObjectUtil.init();
@@ -273,7 +277,7 @@ public class MockerNodeContext implements BlockchainQueryService {
public LedgerInfo getLedger(HashDigest ledgerHash) {
return queryService.getLedger(ledgerHash);
}
@Override
public LedgerAdminInfo getLedgerAdminInfo(HashDigest ledgerHash) {
return queryService.getLedgerAdminInfo(ledgerHash);
@@ -410,7 +414,7 @@ public class MockerNodeContext implements BlockchainQueryService {
}

@Override
public ContractInfo getContract(HashDigest ledgerHash, String address) {
public ContractInfo getContract(HashDigest ledgerHash, String address) {
return queryService.getContract(ledgerHash, address);
}

@@ -443,8 +447,8 @@ public class MockerNodeContext implements BlockchainQueryService {
LedgerEditor newEditor = ledgerRepository.createNextBlock();
LedgerBlock latestBlock = ledgerRepository.getLatestBlock();
LedgerDataset previousDataSet = ledgerRepository.getDataSet(latestBlock);
TransactionBatchProcessor txProc = new TransactionBatchProcessor(newEditor, previousDataSet, opHandler,
ledgerManager);
TransactionBatchProcessor txProc = new TransactionBatchProcessor(newEditor,
previousDataSet, opHandler, ledgerManager);
TransactionResponse txResp = txProc.schedule(txRequest);
TransactionBatchResultHandle handle = txProc.prepare();
handle.commit();


+ 2
- 2
source/tools/tools-mocker/src/main/java/com/jd/blockchain/mocker/handler/MockerContractExeHandle.java View File

@@ -16,7 +16,7 @@ import com.jd.blockchain.ledger.core.LedgerQueryService;
import com.jd.blockchain.ledger.core.LedgerService;
import com.jd.blockchain.ledger.core.OperationHandle;
import com.jd.blockchain.ledger.core.OperationHandleContext;
import com.jd.blockchain.ledger.core.TransactionRequestContext;
import com.jd.blockchain.ledger.core.TransactionRequestExtension;
import com.jd.blockchain.ledger.core.handles.ContractLedgerContext;
import com.jd.blockchain.mocker.proxy.ExecutorProxy;

@@ -29,7 +29,7 @@ public class MockerContractExeHandle implements OperationHandle {
private HashDigest ledgerHash;

@Override
public BytesValue process(Operation op, LedgerDataset dataset, TransactionRequestContext requestContext,
public BytesValue process(Operation op, LedgerDataset dataset, TransactionRequestExtension requestContext,
LedgerDataset previousBlockDataset, OperationHandleContext opHandleContext, LedgerService ledgerService) {
ContractEventSendOperation contractOP = (ContractEventSendOperation) op;



Loading…
Cancel
Save