# Conflicts: # source/base/src/main/java/com/jd/blockchain/consts/DataCodes.java # source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerAdminAccount.java # source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/ParticipantCertData.java # source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/ParticipantDataset.java # source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/DefaultOperationHandleRegisteration.java # source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/ContractInvokingTest.java # source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/LedgerManagerTest.java # source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/core/TransactionSetTest.java # source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/LedgerInitProperties.java # source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ClientOperator.java # source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ConsensusParticipantData.java # source/peer/src/main/java/com/jd/blockchain/peer/web/ManagementController.java # source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/converters/ClientResolveUtil.java # source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/perf/LedgerPerformanceTest.java # source/test/test-integration/src/main/java/test/com/jd/blockchain/intgr/perf/Utils.java # source/tools/tools-capability/src/main/java/com/jd/blockchain/capability/service/SettingsInit.java # source/tools/tools-mocker/src/main/java/com/jd/blockchain/mocker/MockerNodeContext.javatags/1.1.0
@@ -0,0 +1,6 @@ | |||||
1、网关节点移除查询接口 HTTP GET ledgers/{ledgerHash}/settings (出于设计合理性原因) | |||||
2、网关节点增加查询接口 HTTP GET ledgers/{ledgerHash}/admininfo ,接口返回指定账本管理配置信息; |
@@ -8,12 +8,4 @@ | |||||
<version>1.1.0-SNAPSHOT</version> | <version>1.1.0-SNAPSHOT</version> | ||||
</parent> | </parent> | ||||
<artifactId>base</artifactId> | <artifactId>base</artifactId> | ||||
<dependencies> | |||||
<dependency> | |||||
<groupId>org.slf4j</groupId> | |||||
<artifactId>slf4j-api</artifactId> | |||||
</dependency> | |||||
</dependencies> | |||||
</project> | </project> |
@@ -8,11 +8,11 @@ package com.jd.blockchain.consts; | |||||
*/ | */ | ||||
public interface DataCodes { | public interface DataCodes { | ||||
public static final int BYTES_VALUE = 0x80; | |||||
public static final int BYTES_VALUE_LIST = 0x81; | |||||
public static final int BYTES_VALUE = 0x080; | |||||
public static final int BYTES_VALUE_LIST = 0x081; | |||||
public static final int BLOCK_CHAIN_IDENTITY = 0x90; | |||||
public static final int BLOCK_CHAIN_IDENTITY = 0x090; | |||||
public static final int BLOCK = 0x100; | public static final int BLOCK = 0x100; | ||||
@@ -22,6 +22,8 @@ public interface DataCodes { | |||||
public static final int DATA_SNAPSHOT = 0x130; | public static final int DATA_SNAPSHOT = 0x130; | ||||
// public static final int LEDGER_ADMIN_DATA = 0x131; | |||||
public static final int TX = 0x200; | public static final int TX = 0x200; | ||||
public static final int TX_LEDGER = 0x201; | public static final int TX_LEDGER = 0x201; | ||||
@@ -55,12 +57,37 @@ public interface DataCodes { | |||||
public static final int TX_RESPONSE = 0x360; | public static final int TX_RESPONSE = 0x360; | ||||
public static final int TX_OP_RESULT = 0x370; | public static final int TX_OP_RESULT = 0x370; | ||||
public static final int TX_OP_ROLE_CONFIGURE = 0x370; | |||||
public static final int TX_OP_ROLE_CONFIGURE_ENTRY = 0x371; | |||||
public static final int TX_OP_USER_ROLES_AUTHORIZE = 0x372; | |||||
public static final int TX_OP_USER_ROLE_AUTHORIZE_ENTRY = 0x373; | |||||
// enum types of permissions; | |||||
public static final int ENUM_TX_PERMISSION = 0x401; | |||||
public static final int ENUM_LEDGER_PERMISSION = 0x402; | |||||
public static final int ENUM_MULTI_ROLES_POLICY = 0x403; | |||||
public static final int PRIVILEGE_SET = 0x410; | |||||
public static final int ROLE_SET = 0x411; | |||||
public static final int SECURITY_INIT_SETTING = 0x420; | |||||
public static final int SECURITY_ROLE_INIT_SETTING = 0x421; | |||||
public static final int SECURITY_USER_AUTH_INIT_SETTING = 0x422; | |||||
// contract types of metadata; | |||||
public static final int METADATA = 0x600; | public static final int METADATA = 0x600; | ||||
public static final int METADATA_V2 = 0x601; | |||||
public static final int METADATA_INIT_SETTING = 0x610; | public static final int METADATA_INIT_SETTING = 0x610; | ||||
public static final int METADATA_INIT_PERMISSION = 0x611; | |||||
public static final int METADATA_INIT_PROPOSAL = 0x611; | |||||
public static final int METADATA_INIT_DECISION = 0x612; | public static final int METADATA_INIT_DECISION = 0x612; | ||||
@@ -68,6 +95,15 @@ public interface DataCodes { | |||||
public static final int METADATA_CONSENSUS_PARTICIPANT = 0x621; | public static final int METADATA_CONSENSUS_PARTICIPANT = 0x621; | ||||
// public static final int METADATA_CONSENSUS_NODE = 0x630; | |||||
// | |||||
// public static final int METADATA_CONSENSUS_SETTING = 0x631; | |||||
// | |||||
// public static final int METADATA_PARTICIPANT_INFO = 0x640; | |||||
public static final int METADATA_CRYPTO_SETTING = 0x642; | |||||
// public static final int METADATA_CONSENSUS_NODE = 0x630; | // public static final int METADATA_CONSENSUS_NODE = 0x630; | ||||
public static final int METADATA_CONSENSUS_SETTING = 0x631; | public static final int METADATA_CONSENSUS_SETTING = 0x631; | ||||
@@ -88,11 +124,10 @@ public interface DataCodes { | |||||
public static final int DATA = 0x900; | public static final int DATA = 0x900; | ||||
//contract related; | |||||
// contract related; | |||||
public static final int CONTRACT = 0xA00; | public static final int CONTRACT = 0xA00; | ||||
//...0xA19 | |||||
// ...0xA19 | |||||
public static final int HASH = 0xB00; | public static final int HASH = 0xB00; | ||||
public static final int HASH_OBJECT = 0xB10; | public static final int HASH_OBJECT = 0xB10; | ||||
@@ -21,10 +21,10 @@ import com.jd.blockchain.consensus.mq.settings.MsgQueueConsensusSettings; | |||||
import com.jd.blockchain.consensus.mq.settings.MsgQueueNetworkSettings; | import com.jd.blockchain.consensus.mq.settings.MsgQueueNetworkSettings; | ||||
import com.jd.blockchain.consensus.mq.settings.MsgQueueNodeSettings; | import com.jd.blockchain.consensus.mq.settings.MsgQueueNodeSettings; | ||||
import com.jd.blockchain.crypto.AddressEncoding; | import com.jd.blockchain.crypto.AddressEncoding; | ||||
import com.jd.blockchain.crypto.KeyGenUtils; | |||||
import com.jd.blockchain.crypto.PubKey; | import com.jd.blockchain.crypto.PubKey; | ||||
import com.jd.blockchain.ledger.ParticipantInfo; | import com.jd.blockchain.ledger.ParticipantInfo; | ||||
import com.jd.blockchain.ledger.ParticipantNode; | import com.jd.blockchain.ledger.ParticipantNode; | ||||
import com.jd.blockchain.tools.keygen.KeyGenCommand; | |||||
import com.jd.blockchain.utils.Bytes; | import com.jd.blockchain.utils.Bytes; | ||||
import com.jd.blockchain.utils.PropertiesUtils; | import com.jd.blockchain.utils.PropertiesUtils; | ||||
import com.jd.blockchain.utils.codec.Base58Utils; | import com.jd.blockchain.utils.codec.Base58Utils; | ||||
@@ -134,7 +134,7 @@ public class MsgQueueConsensusSettingsBuilder implements ConsensusSettingsBuilde | |||||
String keyOfPubkey = nodeKey(PUBKEY_PATTERN, id); | String keyOfPubkey = nodeKey(PUBKEY_PATTERN, id); | ||||
String base58PubKey = PropertiesUtils.getRequiredProperty(resolvingProps, keyOfPubkey); | String base58PubKey = PropertiesUtils.getRequiredProperty(resolvingProps, keyOfPubkey); | ||||
PubKey pubKey = KeyGenCommand.decodePubKey(base58PubKey); | |||||
PubKey pubKey = KeyGenUtils.decodePubKey(base58PubKey); | |||||
// PubKey pubKey = new PubKey(Base58Utils.decode(base58PubKey)); | // PubKey pubKey = new PubKey(Base58Utils.decode(base58PubKey)); | ||||
resolvingProps.remove(keyOfPubkey); | resolvingProps.remove(keyOfPubkey); | ||||
@@ -7,12 +7,12 @@ import java.io.InputStream; | |||||
import com.jd.blockchain.binaryproto.DataContractRegistry; | import com.jd.blockchain.binaryproto.DataContractRegistry; | ||||
import com.jd.blockchain.crypto.HashDigest; | import com.jd.blockchain.crypto.HashDigest; | ||||
import com.jd.blockchain.crypto.KeyGenUtils; | |||||
import com.jd.blockchain.crypto.PrivKey; | import com.jd.blockchain.crypto.PrivKey; | ||||
import com.jd.blockchain.crypto.PubKey; | import com.jd.blockchain.crypto.PubKey; | ||||
import com.jd.blockchain.ledger.*; | import com.jd.blockchain.ledger.*; | ||||
import com.jd.blockchain.sdk.BlockchainService; | import com.jd.blockchain.sdk.BlockchainService; | ||||
import com.jd.blockchain.sdk.client.GatewayServiceFactory; | import com.jd.blockchain.sdk.client.GatewayServiceFactory; | ||||
import com.jd.blockchain.tools.keygen.KeyGenCommand; | |||||
import com.jd.blockchain.utils.Bytes; | import com.jd.blockchain.utils.Bytes; | ||||
import com.jd.blockchain.utils.codec.Base58Utils; | import com.jd.blockchain.utils.codec.Base58Utils; | ||||
import com.jd.blockchain.utils.net.NetworkAddress; | import com.jd.blockchain.utils.net.NetworkAddress; | ||||
@@ -30,8 +30,8 @@ public enum ContractDeployExeUtil { | |||||
PubKey pub = null; | PubKey pub = null; | ||||
PrivKey prv = null; | PrivKey prv = null; | ||||
try { | try { | ||||
prv = KeyGenCommand.readPrivKey(prvPath, KeyGenCommand.encodePassword(rawPassword)); | |||||
pub = KeyGenCommand.readPubKey(pubPath); | |||||
prv = KeyGenUtils.readPrivKey(prvPath, KeyGenUtils.encodePassword(rawPassword)); | |||||
pub = KeyGenUtils.readPubKey(pubPath); | |||||
} catch (Exception e) { | } catch (Exception e) { | ||||
e.printStackTrace(); | e.printStackTrace(); | ||||
@@ -47,7 +47,7 @@ public enum ContractDeployExeUtil { | |||||
BlockchainKeypair contractKeyPair = BlockchainKeyGenerator.getInstance().generate(); | BlockchainKeypair contractKeyPair = BlockchainKeyGenerator.getInstance().generate(); | ||||
pub = contractKeyPair.getPubKey(); | pub = contractKeyPair.getPubKey(); | ||||
}else { | }else { | ||||
pub = KeyGenCommand.readPubKey(pubPath); | |||||
pub = KeyGenUtils.readPubKey(pubPath); | |||||
} | } | ||||
} catch (Exception e) { | } catch (Exception e) { | ||||
@@ -1,10 +1,10 @@ | |||||
package com.jd.blockchain; | package com.jd.blockchain; | ||||
import com.jd.blockchain.crypto.HashDigest; | import com.jd.blockchain.crypto.HashDigest; | ||||
import com.jd.blockchain.crypto.KeyGenUtils; | |||||
import com.jd.blockchain.crypto.PrivKey; | import com.jd.blockchain.crypto.PrivKey; | ||||
import com.jd.blockchain.crypto.PubKey; | import com.jd.blockchain.crypto.PubKey; | ||||
import com.jd.blockchain.ledger.BlockchainKeypair; | import com.jd.blockchain.ledger.BlockchainKeypair; | ||||
import com.jd.blockchain.tools.keygen.KeyGenCommand; | |||||
import com.jd.blockchain.utils.StringUtils; | import com.jd.blockchain.utils.StringUtils; | ||||
import com.jd.blockchain.utils.codec.Base58Utils; | import com.jd.blockchain.utils.codec.Base58Utils; | ||||
import com.jd.blockchain.utils.io.FileUtils; | import com.jd.blockchain.utils.io.FileUtils; | ||||
@@ -102,8 +102,8 @@ public class ContractDeployMojo extends AbstractMojo { | |||||
byte[] contractBytes = FileUtils.readBytes(contractPath); | byte[] contractBytes = FileUtils.readBytes(contractPath); | ||||
PrivKey prv = KeyGenCommand.decodePrivKeyWithRawPassword(prvKey, password); | |||||
PubKey pub = KeyGenCommand.decodePubKey(pubKey); | |||||
PrivKey prv = KeyGenUtils.decodePrivKeyWithRawPassword(prvKey, password); | |||||
PubKey pub = KeyGenUtils.decodePubKey(pubKey); | |||||
BlockchainKeypair blockchainKeyPair = new BlockchainKeypair(pub, prv); | BlockchainKeypair blockchainKeyPair = new BlockchainKeypair(pub, prv); | ||||
HashDigest ledgerHash = new HashDigest(Base58Utils.decode(ledger)); | HashDigest ledgerHash = new HashDigest(Base58Utils.decode(ledger)); | ||||
@@ -0,0 +1,187 @@ | |||||
package com.jd.blockchain.crypto; | |||||
import java.util.Arrays; | |||||
import javax.crypto.SecretKey; | |||||
import com.jd.blockchain.utils.ConsoleUtils; | |||||
import com.jd.blockchain.utils.codec.Base58Utils; | |||||
import com.jd.blockchain.utils.io.BytesUtils; | |||||
import com.jd.blockchain.utils.io.FileUtils; | |||||
import com.jd.blockchain.utils.security.AESUtils; | |||||
import com.jd.blockchain.utils.security.DecryptionException; | |||||
import com.jd.blockchain.utils.security.ShaUtils; | |||||
public class KeyGenUtils { | |||||
private static final byte[] PUB_KEY_FILE_MAGICNUM = { (byte) 0xFF, 112, 117, 98 }; | |||||
private static final byte[] PRIV_KEY_FILE_MAGICNUM = { (byte) 0x00, 112, 114, 118 }; | |||||
/** | |||||
* 公钥编码输出为 Base58 字符; | |||||
* | |||||
* @param pubKey | |||||
* @return | |||||
*/ | |||||
public static String encodePubKey(PubKey pubKey) { | |||||
byte[] pubKeyBytes = BytesUtils.concat(PUB_KEY_FILE_MAGICNUM, pubKey.toBytes()); | |||||
String base58PubKey = Base58Utils.encode(pubKeyBytes); | |||||
return base58PubKey; | |||||
} | |||||
public static PubKey decodePubKey(String base58PubKey) { | |||||
byte[] keyBytes = Base58Utils.decode(base58PubKey); | |||||
return decodePubKey(keyBytes); | |||||
} | |||||
public static String encodePrivKey(PrivKey privKey, String base58Pwd) { | |||||
byte[] pwdBytes = Base58Utils.decode(base58Pwd); | |||||
return encodePrivKey(privKey, pwdBytes); | |||||
} | |||||
public static String encodePrivKey(PrivKey privKey, byte[] pwdBytes) { | |||||
byte[] encodedPrivKeyBytes = encryptPrivKey(privKey, pwdBytes); | |||||
String base58PrivKey = Base58Utils.encode(encodedPrivKeyBytes); | |||||
return base58PrivKey; | |||||
} | |||||
public static byte[] encryptPrivKey(PrivKey privKey, byte[] pwdBytes) { | |||||
SecretKey userKey = AESUtils.generateKey128(pwdBytes); | |||||
byte[] encryptedPrivKeyBytes = AESUtils.encrypt(privKey.toBytes(), userKey); | |||||
return BytesUtils.concat(PRIV_KEY_FILE_MAGICNUM, encryptedPrivKeyBytes); | |||||
} | |||||
/** | |||||
* @param encodedPubKeyBytes | |||||
* @return | |||||
*/ | |||||
private static PubKey decodePubKeyBytes(byte[] encodedPubKeyBytes) { | |||||
byte[] pubKeyBytes = Arrays.copyOfRange(encodedPubKeyBytes, PUB_KEY_FILE_MAGICNUM.length, | |||||
encodedPubKeyBytes.length); | |||||
return new PubKey(pubKeyBytes); | |||||
} | |||||
public static PrivKey decryptedPrivKeyBytes(byte[] encodedPrivKeyBytes, byte[] pwdBytes) { | |||||
// Read privKye; | |||||
SecretKey userKey = AESUtils.generateKey128(pwdBytes); | |||||
byte[] encryptedKeyBytes = Arrays.copyOfRange(encodedPrivKeyBytes, PRIV_KEY_FILE_MAGICNUM.length, | |||||
encodedPrivKeyBytes.length); | |||||
try { | |||||
byte[] plainKeyBytes = AESUtils.decrypt(encryptedKeyBytes, userKey); | |||||
return new PrivKey(plainKeyBytes); | |||||
} catch (DecryptionException e) { | |||||
throw new DecryptionException("Invalid password!", e); | |||||
} | |||||
} | |||||
public static PubKey readPubKey(String keyFile) { | |||||
String base58KeyString = FileUtils.readText(keyFile); | |||||
return decodePubKey(base58KeyString); | |||||
} | |||||
/** | |||||
* 解码公钥; | |||||
* | |||||
* @param encodedPubKeyBytes 从公钥; | |||||
* @return | |||||
*/ | |||||
public static PubKey decodePubKey(byte[] encodedPubKeyBytes) { | |||||
if (BytesUtils.startsWith(encodedPubKeyBytes, PUB_KEY_FILE_MAGICNUM)) { | |||||
// Read pubKey; | |||||
return decodePubKeyBytes(encodedPubKeyBytes); | |||||
} | |||||
throw new IllegalArgumentException("The specified bytes is not valid PubKey generated by the KeyGen tool!"); | |||||
} | |||||
/** | |||||
* 从控制台读取加密口令,以二进制数组形式返回原始口令的一次SHA256的结果; | |||||
* | |||||
* @return | |||||
*/ | |||||
public static byte[] readPassword() { | |||||
byte[] pwdBytes = ConsoleUtils.readPassword(); | |||||
return ShaUtils.hash_256(pwdBytes); | |||||
} | |||||
/** | |||||
* 对指定的原始密码进行编码生成用于加解密的密码; | |||||
* | |||||
* @param rawPassword | |||||
* @return | |||||
*/ | |||||
public static byte[] encodePassword(String rawPassword) { | |||||
byte[] pwdBytes = BytesUtils.toBytes(rawPassword, "UTF-8"); | |||||
return ShaUtils.hash_256(pwdBytes); | |||||
} | |||||
/** | |||||
* 对指定的原始密码进行编码生成用于加解密的密码; | |||||
* | |||||
* @param rawPassword | |||||
* @return | |||||
*/ | |||||
public static String encodePasswordAsBase58(String rawPassword) { | |||||
return Base58Utils.encode(encodePassword(rawPassword)); | |||||
} | |||||
/** | |||||
* 从控制台读取加密口令,以Base58字符串形式返回口令的一次SHA256的结果; | |||||
* | |||||
* @return | |||||
*/ | |||||
public static String readPasswordString() { | |||||
return Base58Utils.encode(readPassword()); | |||||
} | |||||
public static PrivKey readPrivKey(String keyFile, String base58Pwd) { | |||||
return readPrivKey(keyFile, Base58Utils.decode(base58Pwd)); | |||||
} | |||||
/** | |||||
* 从文件读取私钥; | |||||
* | |||||
* @param keyFile | |||||
* @param pwdBytes | |||||
* @return | |||||
*/ | |||||
public static PrivKey readPrivKey(String keyFile, byte[] pwdBytes) { | |||||
String base58KeyString = FileUtils.readText(keyFile); | |||||
byte[] keyBytes = Base58Utils.decode(base58KeyString); | |||||
if (!BytesUtils.startsWith(keyBytes, PRIV_KEY_FILE_MAGICNUM)) { | |||||
throw new IllegalArgumentException("The specified file is not a private key file!"); | |||||
} | |||||
return decryptedPrivKeyBytes(keyBytes, pwdBytes); | |||||
} | |||||
public static PrivKey decodePrivKey(String base58Key, String base58Pwd) { | |||||
byte[] decryptedKey = Base58Utils.decode(base58Pwd); | |||||
return decodePrivKey(base58Key, decryptedKey); | |||||
} | |||||
public static PrivKey decodePrivKey(String base58Key, byte[] pwdBytes) { | |||||
byte[] keyBytes = Base58Utils.decode(base58Key); | |||||
if (!BytesUtils.startsWith(keyBytes, PRIV_KEY_FILE_MAGICNUM)) { | |||||
throw new IllegalArgumentException("The specified file is not a private key file!"); | |||||
} | |||||
return decryptedPrivKeyBytes(keyBytes, pwdBytes); | |||||
} | |||||
public static PrivKey decodePrivKeyWithRawPassword(String base58Key, String rawPassword) { | |||||
byte[] pwdBytes = encodePassword(rawPassword); | |||||
byte[] keyBytes = Base58Utils.decode(base58Key); | |||||
if (!BytesUtils.startsWith(keyBytes, PRIV_KEY_FILE_MAGICNUM)) { | |||||
throw new IllegalArgumentException("The specified file is not a private key file!"); | |||||
} | |||||
return decryptedPrivKeyBytes(keyBytes, pwdBytes); | |||||
} | |||||
public static boolean isPubKeyBytes(byte[] keyBytes) { | |||||
return BytesUtils.startsWith(keyBytes, PUB_KEY_FILE_MAGICNUM); | |||||
} | |||||
public static boolean isPrivKeyBytes(byte[] keyBytes) { | |||||
return BytesUtils.startsWith(keyBytes, PRIV_KEY_FILE_MAGICNUM); | |||||
} | |||||
} |
@@ -18,15 +18,13 @@ public class GatewayBooter { | |||||
writePID(); | writePID(); | ||||
GatewayServerBooter.main(args); | GatewayServerBooter.main(args); | ||||
} catch (Exception e) { | } catch (Exception e) { | ||||
e.printStackTrace(); | |||||
System.err.println("Error!!! --[" + e.getClass().getName() + "] " + e.getMessage()); | System.err.println("Error!!! --[" + e.getClass().getName() + "] " + e.getMessage()); | ||||
} | } | ||||
} | } | ||||
private static final void writePID() throws Exception { | private static final void writePID() throws Exception { | ||||
URL url = GatewayBooter.class | |||||
.getProtectionDomain() | |||||
.getCodeSource() | |||||
.getLocation(); | |||||
URL url = GatewayBooter.class.getProtectionDomain().getCodeSource().getLocation(); | |||||
String currPath = java.net.URLDecoder.decode(url.getPath(), "UTF-8"); | String currPath = java.net.URLDecoder.decode(url.getPath(), "UTF-8"); | ||||
if (currPath.contains("!/")) { | if (currPath.contains("!/")) { | ||||
currPath = currPath.substring(5, currPath.indexOf("!/")); | currPath = currPath.substring(5, currPath.indexOf("!/")); | ||||
@@ -40,6 +38,10 @@ public class GatewayBooter { | |||||
String pidFilePath = homeDir + File.separator + "bin" + File.separator + "PID.log"; | String pidFilePath = homeDir + File.separator + "bin" + File.separator + "PID.log"; | ||||
File pidFile = new File(pidFilePath); | File pidFile = new File(pidFilePath); | ||||
if (!pidFile.exists()) { | if (!pidFile.exists()) { | ||||
File dir = pidFile.getParentFile(); | |||||
if (!dir.exists()) { | |||||
dir.mkdirs(); | |||||
} | |||||
pidFile.createNewFile(); | pidFile.createNewFile(); | ||||
} | } | ||||
String name = ManagementFactory.getRuntimeMXBean().getName(); | String name = ManagementFactory.getRuntimeMXBean().getName(); | ||||
@@ -75,7 +75,6 @@ | |||||
<dependency> | <dependency> | ||||
<groupId>commons-io</groupId> | <groupId>commons-io</groupId> | ||||
<artifactId>commons-io</artifactId> | <artifactId>commons-io</artifactId> | ||||
<version>${commons-io.version}</version> | |||||
</dependency> | </dependency> | ||||
<dependency> | <dependency> | ||||
@@ -98,18 +97,13 @@ | |||||
<dependency> | <dependency> | ||||
<groupId>org.springframework.boot</groupId> | <groupId>org.springframework.boot</groupId> | ||||
<artifactId>spring-boot-starter-web</artifactId> | <artifactId>spring-boot-starter-web</artifactId> | ||||
<exclusions> | |||||
<exclusion> | |||||
<groupId>org.springframework.boot</groupId> | |||||
<artifactId>spring-boot-starter-logging</artifactId> | |||||
</exclusion> | |||||
</exclusions> | |||||
</dependency> | </dependency> | ||||
<dependency> | |||||
<!-- <dependency> | |||||
<groupId>org.springframework.boot</groupId> | <groupId>org.springframework.boot</groupId> | ||||
<artifactId>spring-boot-starter-log4j2</artifactId> | <artifactId>spring-boot-starter-log4j2</artifactId> | ||||
</dependency> | |||||
</dependency> --> | |||||
<dependency> | <dependency> | ||||
<groupId>org.springframework.boot</groupId> | <groupId>org.springframework.boot</groupId> | ||||
@@ -5,20 +5,20 @@ import java.io.InputStream; | |||||
import java.util.ArrayList; | import java.util.ArrayList; | ||||
import java.util.List; | import java.util.List; | ||||
import com.jd.blockchain.gateway.web.BlockBrowserController; | |||||
import org.apache.commons.io.FileUtils; | import org.apache.commons.io.FileUtils; | ||||
import org.springframework.boot.SpringApplication; | import org.springframework.boot.SpringApplication; | ||||
import org.springframework.context.ConfigurableApplicationContext; | import org.springframework.context.ConfigurableApplicationContext; | ||||
import org.springframework.core.io.ClassPathResource; | import org.springframework.core.io.ClassPathResource; | ||||
import com.jd.blockchain.crypto.AsymmetricKeypair; | import com.jd.blockchain.crypto.AsymmetricKeypair; | ||||
import com.jd.blockchain.crypto.KeyGenUtils; | |||||
import com.jd.blockchain.crypto.PrivKey; | import com.jd.blockchain.crypto.PrivKey; | ||||
import com.jd.blockchain.crypto.PubKey; | import com.jd.blockchain.crypto.PubKey; | ||||
import com.jd.blockchain.tools.keygen.KeyGenCommand; | |||||
import com.jd.blockchain.gateway.web.BlockBrowserController; | |||||
import com.jd.blockchain.utils.ArgumentSet; | import com.jd.blockchain.utils.ArgumentSet; | ||||
import com.jd.blockchain.utils.ArgumentSet.ArgEntry; | |||||
import com.jd.blockchain.utils.BaseConstant; | import com.jd.blockchain.utils.BaseConstant; | ||||
import com.jd.blockchain.utils.ConsoleUtils; | import com.jd.blockchain.utils.ConsoleUtils; | ||||
import com.jd.blockchain.utils.ArgumentSet.ArgEntry; | |||||
public class GatewayServerBooter { | public class GatewayServerBooter { | ||||
@@ -88,19 +88,19 @@ public class GatewayServerBooter { | |||||
String base58Pwd = config.keys().getDefault().getPrivKeyPassword(); | String base58Pwd = config.keys().getDefault().getPrivKeyPassword(); | ||||
if (base58Pwd == null || base58Pwd.length() == 0) { | if (base58Pwd == null || base58Pwd.length() == 0) { | ||||
base58Pwd = KeyGenCommand.readPasswordString(); | |||||
base58Pwd = KeyGenUtils.readPasswordString(); | |||||
} | } | ||||
// 加载密钥; | // 加载密钥; | ||||
PubKey pubKey = KeyGenCommand.decodePubKey(config.keys().getDefault().getPubKeyValue()); | |||||
PubKey pubKey = KeyGenUtils.decodePubKey(config.keys().getDefault().getPubKeyValue()); | |||||
PrivKey privKey = null; | PrivKey privKey = null; | ||||
String base58PrivKey = config.keys().getDefault().getPrivKeyValue(); | String base58PrivKey = config.keys().getDefault().getPrivKeyValue(); | ||||
if (base58PrivKey == null) { | if (base58PrivKey == null) { | ||||
//注:GatewayConfigProperties 确保了 PrivKeyValue 和 PrivKeyPath 必有其一; | //注:GatewayConfigProperties 确保了 PrivKeyValue 和 PrivKeyPath 必有其一; | ||||
privKey = KeyGenCommand.readPrivKey(config.keys().getDefault().getPrivKeyPath(), base58Pwd); | |||||
privKey = KeyGenUtils.readPrivKey(config.keys().getDefault().getPrivKeyPath(), base58Pwd); | |||||
} else { | } else { | ||||
privKey = KeyGenCommand.decodePrivKey(base58PrivKey, base58Pwd); | |||||
privKey = KeyGenUtils.decodePrivKey(base58PrivKey, base58Pwd); | |||||
} | } | ||||
defaultKeyPair = new AsymmetricKeypair(pubKey, privKey); | defaultKeyPair = new AsymmetricKeypair(pubKey, privKey); | ||||
} | } | ||||
@@ -1,50 +0,0 @@ | |||||
package com.jd.blockchain.gateway.service; | |||||
import com.jd.blockchain.crypto.HashDigest; | |||||
import com.jd.blockchain.ledger.ParticipantNode; | |||||
import com.jd.blockchain.sdk.ContractSettings; | |||||
import com.jd.blockchain.sdk.LedgerInitSettings; | |||||
import com.jd.blockchain.utils.Bytes; | |||||
/** | |||||
* queryService only for gateway; | |||||
* @Author zhaogw | |||||
* @Date 2019/2/22 10:37 | |||||
*/ | |||||
public interface GatewayQueryService { | |||||
/** | |||||
* get all ledgers hashs; | |||||
* @param fromIndex | |||||
* @param count | |||||
*/ | |||||
HashDigest[] getLedgersHash(int fromIndex, int count); | |||||
/** | |||||
* get the participants by range; | |||||
* @param ledgerHash | |||||
* @param fromIndex | |||||
* @param count | |||||
* @return | |||||
*/ | |||||
ParticipantNode[] getConsensusParticipants(HashDigest ledgerHash, int fromIndex, int count); | |||||
/** | |||||
* 获取账本初始化配置信息 | |||||
* | |||||
* @param ledgerHash | |||||
* 账本Hash | |||||
* @return | |||||
*/ | |||||
LedgerInitSettings getLedgerInitSettings(HashDigest ledgerHash); | |||||
/** | |||||
* 获取账本指定合约信息 | |||||
* | |||||
* @param ledgerHash | |||||
* 账本Hash | |||||
* @param address | |||||
* 合约地址 | |||||
* @return | |||||
*/ | |||||
ContractSettings getContractSettings(HashDigest ledgerHash, String address); | |||||
} |
@@ -1,144 +0,0 @@ | |||||
package com.jd.blockchain.gateway.service; | |||||
import com.jd.blockchain.consensus.ConsensusProvider; | |||||
import com.jd.blockchain.consensus.ConsensusProviders; | |||||
import com.jd.blockchain.consensus.ConsensusSettings; | |||||
import com.jd.blockchain.consensus.bftsmart.BftsmartConsensusProvider; | |||||
import com.jd.blockchain.consensus.mq.MsgQueueConsensusProvider; | |||||
import com.jd.blockchain.crypto.HashDigest; | |||||
import com.jd.blockchain.gateway.PeerService; | |||||
import com.jd.blockchain.gateway.decompiler.utils.DecompilerUtils; | |||||
import com.jd.blockchain.ledger.ContractInfo; | |||||
import com.jd.blockchain.ledger.LedgerMetadata; | |||||
import com.jd.blockchain.ledger.ParticipantNode; | |||||
import com.jd.blockchain.sdk.ContractSettings; | |||||
import com.jd.blockchain.sdk.LedgerInitSettings; | |||||
import com.jd.blockchain.utils.QueryUtil; | |||||
import com.jd.blockchain.utils.codec.HexUtils; | |||||
import org.springframework.beans.factory.annotation.Autowired; | |||||
import org.springframework.stereotype.Component; | |||||
import java.util.Arrays; | |||||
/** | |||||
* @Author zhaogw | |||||
* @Date 2019/2/22 10:39 | |||||
*/ | |||||
@Component | |||||
public class GatewayQueryServiceHandler implements GatewayQueryService { | |||||
@Autowired | |||||
private PeerService peerService; | |||||
@Override | |||||
public HashDigest[] getLedgersHash(int fromIndex, int count) { | |||||
HashDigest ledgersHash[] = peerService.getQueryService().getLedgerHashs(); | |||||
int indexAndCount[] = QueryUtil.calFromIndexAndCount(fromIndex,count,ledgersHash.length); | |||||
HashDigest ledgersHashNew[] = Arrays.copyOfRange(ledgersHash,indexAndCount[0],indexAndCount[0]+indexAndCount[1]); | |||||
return ledgersHashNew; | |||||
} | |||||
@Override | |||||
public ParticipantNode[] getConsensusParticipants(HashDigest ledgerHash, int fromIndex, int count) { | |||||
ParticipantNode participantNode[] = peerService.getQueryService().getConsensusParticipants(ledgerHash); | |||||
int indexAndCount[] = QueryUtil.calFromIndexAndCount(fromIndex,count,participantNode.length); | |||||
ParticipantNode participantNodesNew[] = Arrays.copyOfRange(participantNode,indexAndCount[0],indexAndCount[0]+indexAndCount[1]); | |||||
return participantNodesNew; | |||||
} | |||||
@Override | |||||
public LedgerInitSettings getLedgerInitSettings(HashDigest ledgerHash) { | |||||
ParticipantNode[] participantNodes = peerService.getQueryService().getConsensusParticipants(ledgerHash); | |||||
LedgerMetadata ledgerMetadata = peerService.getQueryService().getLedgerMetadata(ledgerHash); | |||||
return initLedgerInitSettings(participantNodes, ledgerMetadata); | |||||
} | |||||
@Override | |||||
public ContractSettings getContractSettings(HashDigest ledgerHash, String address) { | |||||
ContractInfo contractInfo = peerService.getQueryService().getContract(ledgerHash, address); | |||||
return contractSettings(contractInfo); | |||||
} | |||||
private ContractSettings contractSettings(ContractInfo contractInfo) { | |||||
ContractSettings contractSettings = new ContractSettings(contractInfo.getAddress(), contractInfo.getPubKey(), contractInfo.getRootHash()); | |||||
byte[] chainCodeBytes = contractInfo.getChainCode(); | |||||
// 将反编译chainCode | |||||
String mainClassJava = DecompilerUtils.decompileMainClassFromBytes(chainCodeBytes); | |||||
contractSettings.setChainCode(mainClassJava); | |||||
return contractSettings; | |||||
} | |||||
/** | |||||
* 初始化账本配置 | |||||
* | |||||
* @param participantNodes | |||||
* 参与方列表 | |||||
* @param ledgerMetadata | |||||
* 账本元数据 | |||||
* @return | |||||
*/ | |||||
private LedgerInitSettings initLedgerInitSettings(ParticipantNode[] participantNodes, LedgerMetadata ledgerMetadata) { | |||||
LedgerInitSettings ledgerInitSettings = new LedgerInitSettings(); | |||||
// 设置参与方 | |||||
ledgerInitSettings.setParticipantNodes(participantNodes); | |||||
// 设置共识设置 | |||||
ledgerInitSettings.setConsensusSettings(initConsensusSettings(ledgerMetadata)); | |||||
// 设置参与方根Hash | |||||
ledgerInitSettings.setParticipantsHash(ledgerMetadata.getParticipantsHash()); | |||||
// 设置算法配置 | |||||
ledgerInitSettings.setCryptoSetting(ledgerMetadata.getSetting().getCryptoSetting()); | |||||
// 设置种子 | |||||
ledgerInitSettings.setSeed(initSeed(ledgerMetadata.getSeed())); | |||||
// 设置共识协议 | |||||
ledgerInitSettings.setConsensusProtocol(ledgerMetadata.getSetting().getConsensusProvider()); | |||||
return ledgerInitSettings; | |||||
} | |||||
/** | |||||
* 初始化账本种子信息 | |||||
* | |||||
* @param seedBytes | |||||
* 种子的字节数组显示 | |||||
* @return | |||||
* 种子以十六进制方式显示,为方便阅读,每隔八个字符中间以"-"分割 | |||||
*/ | |||||
private String initSeed(byte[] seedBytes) { | |||||
String seedString = HexUtils.encode(seedBytes); | |||||
// 每隔八个字符中加入一个一个横线 | |||||
StringBuffer seed = new StringBuffer(); | |||||
for( int i = 0; i < seedString.length(); i++) { | |||||
char c = seedString.charAt(i); | |||||
if (i != 0 && i % 8 == 0) { | |||||
seed.append("-"); | |||||
} | |||||
seed.append(c); | |||||
} | |||||
return seed.toString(); | |||||
} | |||||
/** | |||||
* 初始化共识配置 | |||||
* | |||||
* @param ledgerMetadata | |||||
* 账本元数据 | |||||
* @return | |||||
*/ | |||||
private ConsensusSettings initConsensusSettings(LedgerMetadata ledgerMetadata) { | |||||
String consensusProvider = ledgerMetadata.getSetting().getConsensusProvider(); | |||||
ConsensusProvider provider = ConsensusProviders.getProvider(consensusProvider); | |||||
byte[] consensusSettingsBytes = ledgerMetadata.getSetting().getConsensusSetting().toBytes(); | |||||
return provider.getSettingsFactory().getConsensusSettingsEncoder().decode(consensusSettingsBytes); | |||||
} | |||||
} |
@@ -35,6 +35,9 @@ public class GatewayWebServerConfigurer implements WebMvcConfigurer { | |||||
JSONSerializeUtils.disableCircularReferenceDetect(); | JSONSerializeUtils.disableCircularReferenceDetect(); | ||||
JSONSerializeUtils.configStringSerializer(ByteArray.class); | JSONSerializeUtils.configStringSerializer(ByteArray.class); | ||||
DataContractRegistry.register(BftsmartNodeSettings.class); | DataContractRegistry.register(BftsmartNodeSettings.class); | ||||
DataContractRegistry.register(LedgerAdminInfo.class); | |||||
} | } | ||||
@@ -1,26 +0,0 @@ | |||||
package com.jd.blockchain.ledger.core; | |||||
public interface AccountPrivilege { | |||||
/** | |||||
* 数据“读”的操作码; | |||||
* | |||||
* @return | |||||
*/ | |||||
byte getReadingOpCode(); | |||||
/** | |||||
* “写”的操作码; | |||||
* | |||||
* @return | |||||
*/ | |||||
byte getWrittingOpCode(); | |||||
/** | |||||
* 其它的扩展操作码; | |||||
* | |||||
* @return | |||||
*/ | |||||
byte[] getExtOpCodes(); | |||||
} |
@@ -12,6 +12,7 @@ import com.jd.blockchain.ledger.AccountHeader; | |||||
import com.jd.blockchain.ledger.BytesValue; | import com.jd.blockchain.ledger.BytesValue; | ||||
import com.jd.blockchain.ledger.CryptoSetting; | import com.jd.blockchain.ledger.CryptoSetting; | ||||
import com.jd.blockchain.ledger.LedgerException; | import com.jd.blockchain.ledger.LedgerException; | ||||
import com.jd.blockchain.ledger.MerkleProof; | |||||
import com.jd.blockchain.storage.service.ExPolicyKVStorage; | import com.jd.blockchain.storage.service.ExPolicyKVStorage; | ||||
import com.jd.blockchain.storage.service.VersioningKVStorage; | import com.jd.blockchain.storage.service.VersioningKVStorage; | ||||
import com.jd.blockchain.utils.Bytes; | import com.jd.blockchain.utils.Bytes; | ||||
@@ -48,6 +49,10 @@ public class AccountSet implements Transactional, MerkleProvable { | |||||
public boolean isReadonly() { | public boolean isReadonly() { | ||||
return merkleDataset.isReadonly(); | return merkleDataset.isReadonly(); | ||||
} | } | ||||
void setReadonly() { | |||||
merkleDataset.setReadonly(); | |||||
} | |||||
public AccountSet(CryptoSetting cryptoSetting, String keyPrefix, ExPolicyKVStorage exStorage, | public AccountSet(CryptoSetting cryptoSetting, String keyPrefix, ExPolicyKVStorage exStorage, | ||||
VersioningKVStorage verStorage, AccountAccessPolicy accessPolicy) { | VersioningKVStorage verStorage, AccountAccessPolicy accessPolicy) { | ||||
@@ -65,10 +70,6 @@ public class AccountSet implements Transactional, MerkleProvable { | |||||
this.accessPolicy = accessPolicy; | this.accessPolicy = accessPolicy; | ||||
} | } | ||||
// public HashDigest getAccountRootHash() { | |||||
// return merkleDataset.getRootHash(); | |||||
// } | |||||
@Override | @Override | ||||
public HashDigest getRootHash() { | public HashDigest getRootHash() { | ||||
return merkleDataset.getRootHash(); | return merkleDataset.getRootHash(); | ||||
@@ -1,168 +0,0 @@ | |||||
//package com.jd.blockchain.ledger.core; | |||||
// | |||||
//import com.jd.blockchain.crypto.hash.HashDigest; | |||||
// | |||||
//import my.utils.Scratchable; | |||||
//import my.utils.io.ByteArray; | |||||
//import my.utils.io.BytesUtils; | |||||
//import my.utils.io.ExistancePolicyKVStorage; | |||||
//import my.utils.io.VersioningKVStorage; | |||||
// | |||||
///** | |||||
// * 可进行授权控制的数据集合; | |||||
// * | |||||
// * @author huanghaiquan | |||||
// * | |||||
// */ | |||||
//public class AuthorizableDataSet implements Scratchable { | |||||
// | |||||
// public static final String DATA_PREFIX = "DATA" + LedgerConsts.KEY_SEPERATOR; | |||||
//// public static final String PRIVILEGE_PREFIX = "PRVL" + LedgerConsts.KEY_SEPERATOR; | |||||
// | |||||
// private static final String DEFAULT_PRIVILEGE_KEY = "%"; | |||||
// | |||||
// private DataAccessable accessable; | |||||
// | |||||
// protected MerkleDataSet data; | |||||
// | |||||
//// private PrivilegeDataSet privileges; | |||||
// | |||||
// /** | |||||
// * Create a new Account instance; | |||||
// * | |||||
// * @param address | |||||
// * @param pubKey | |||||
// */ | |||||
// protected AuthorizableDataSet(CryptoSetting merkleTreeSetting, ExistancePolicyKVStorage simpleStorage, | |||||
// VersioningKVStorage versioningStorage) { | |||||
// this(null, merkleTreeSetting, null, simpleStorage, versioningStorage); | |||||
// } | |||||
// | |||||
// protected AuthorizableDataSet(byte[] dataRootHash, CryptoSetting merkleTreeSetting, byte[] privilegeRootHash, | |||||
// ExistancePolicyKVStorage simpleStorage, VersioningKVStorage versioningStorage) { | |||||
// this(dataRootHash, merkleTreeSetting, privilegeRootHash, simpleStorage, versioningStorage, false); | |||||
// } | |||||
// | |||||
// protected AuthorizableDataSet(byte[] dataRootHash, CryptoSetting merkleTreeSetting, byte[] privilegeRootHash, | |||||
// ExistancePolicyKVStorage simpleStorage, VersioningKVStorage versioningStorage, boolean readonly) { | |||||
// this.data = new MerkleDataSet(dataRootHash, merkleTreeSetting, | |||||
// PrefixAppender.prefix(DATA_PREFIX, simpleStorage), | |||||
// PrefixAppender.prefix(DATA_PREFIX, versioningStorage), readonly); | |||||
// | |||||
//// this.privileges = new PrivilegeDataSet(privilegeRootHash, merkleTreeSetting, | |||||
//// PrefixAppender.prefix(PRIVILEGE_PREFIX, simpleStorage), | |||||
//// PrefixAppender.prefix(PRIVILEGE_PREFIX, versioningStorage), readonly); | |||||
// } | |||||
// | |||||
// public ByteArray getDataRootHash() { | |||||
// return data.getRootHash(); | |||||
// } | |||||
// | |||||
//// public ByteArray getPrivilegeRootHash() { | |||||
//// return privileges.getRootHash(); | |||||
//// } | |||||
// | |||||
// /** | |||||
// * | |||||
// * @param userAddress | |||||
// * @param op | |||||
// * @param enable | |||||
// */ | |||||
// public void setPrivilege(String userAddress, byte op, boolean enable) { | |||||
// | |||||
// } | |||||
// | |||||
// /** | |||||
// * | |||||
// * @param op | |||||
// * @param enable | |||||
// */ | |||||
// public void setDefaultPrivilege(byte op, boolean enable) { | |||||
// } | |||||
// | |||||
// public boolean checkCurrentUserPrivilege() { | |||||
// return false; | |||||
// } | |||||
// | |||||
// /** | |||||
// * Return the latest version entry associated the specified key; If the key | |||||
// * doesn't exist, then return -1; | |||||
// * | |||||
// * @param key | |||||
// * @return | |||||
// */ | |||||
// public long getVersion(String key) { | |||||
// return data.getVersion(key); | |||||
// } | |||||
// | |||||
// protected long setString(String key, String value, long version) { | |||||
// checkWritting(); | |||||
// byte[] bytes = BytesUtils.toBytes(value, LedgerConsts.CHARSET); | |||||
// return data.setValue(key, bytes, version); | |||||
// } | |||||
// | |||||
// protected String getString(String key) { | |||||
// checkReading(); | |||||
// byte[] value = data.getValue(key); | |||||
// return BytesUtils.toString(value, LedgerConsts.CHARSET); | |||||
// } | |||||
// | |||||
// protected String getString(String key, long version) { | |||||
// checkReading(); | |||||
// byte[] value = data.getValue(key, version); | |||||
// return BytesUtils.toString(value, LedgerConsts.CHARSET); | |||||
// } | |||||
// | |||||
// protected long setValue(String key, byte[] value, long version) { | |||||
// checkWritting(); | |||||
// return data.setValue(key, value, version); | |||||
// } | |||||
// | |||||
// protected byte[] getValue(String key) { | |||||
// checkReading(); | |||||
// return data.getValue(key); | |||||
// } | |||||
// | |||||
// protected byte[] getValue(String key, long version) { | |||||
// checkReading(); | |||||
// return data.getValue(key, version); | |||||
// } | |||||
// | |||||
// private void checkWritting() { | |||||
// // Check writting enable; | |||||
// } | |||||
// | |||||
// private void checkReading() { | |||||
// // TODO Check privilege of reading; | |||||
// } | |||||
// | |||||
// // /** | |||||
// // * 数据“读”的操作码; | |||||
// // * | |||||
// // * @return | |||||
// // */ | |||||
// // protected abstract AccountPrivilege getPrivilege(); | |||||
// | |||||
// @Override | |||||
// public boolean isUpdated() { | |||||
// return data.isUpdated(); | |||||
//// return data.isUpdated()|| privileges.isUpdated(); | |||||
// } | |||||
// | |||||
// @Override | |||||
// public void commit() { | |||||
// if (data.isUpdated()) { | |||||
// data.commit(); | |||||
// } | |||||
//// if (privileges.isUpdated()) { | |||||
//// privileges.commit(); | |||||
//// } | |||||
// } | |||||
// | |||||
// @Override | |||||
// public void cancel() { | |||||
// data.cancel(); | |||||
//// privileges.cancel(); | |||||
// } | |||||
// | |||||
//} |
@@ -1,40 +0,0 @@ | |||||
package com.jd.blockchain.ledger.core; | |||||
import com.jd.blockchain.ledger.DigitalSignature; | |||||
/** | |||||
* {@link Authorization} 抽象了对特定用户/角色的授权信息; | |||||
* | |||||
* @author huanghaiquan | |||||
* | |||||
*/ | |||||
public interface Authorization { | |||||
/** | |||||
* 被授权用户/角色的地址; | |||||
* | |||||
* @return | |||||
*/ | |||||
String getAddress(); | |||||
/** | |||||
* 授权码;<br> | |||||
* | |||||
* @return | |||||
*/ | |||||
byte[] getCode(); | |||||
/** | |||||
* 授权者的签名; | |||||
* | |||||
* @return | |||||
*/ | |||||
DigitalSignature getSignature(); | |||||
// /** | |||||
// * 授权生成的时间戳; | |||||
// * @return | |||||
// */ | |||||
// long getTs(); | |||||
} |
@@ -1,42 +0,0 @@ | |||||
package com.jd.blockchain.ledger.core; | |||||
import com.jd.blockchain.ledger.DigitalSignature; | |||||
public class AuthorizationVO implements Authorization { | |||||
private String address; | |||||
private byte[] code; | |||||
private DigitalSignature signature; | |||||
@Override | |||||
public String getAddress() { | |||||
return address; | |||||
} | |||||
public void setAddress(String address) { | |||||
this.address = address; | |||||
} | |||||
@Override | |||||
public byte[] getCode() { | |||||
return code; | |||||
} | |||||
public void setCode(byte[] code) { | |||||
this.code = code; | |||||
} | |||||
@Override | |||||
public DigitalSignature getSignature() { | |||||
return signature; | |||||
} | |||||
public void setSignature(DigitalSignature signature) { | |||||
this.signature = signature; | |||||
} | |||||
} |
@@ -8,6 +8,7 @@ import com.jd.blockchain.ledger.BlockchainIdentity; | |||||
import com.jd.blockchain.ledger.BlockchainIdentityData; | import com.jd.blockchain.ledger.BlockchainIdentityData; | ||||
import com.jd.blockchain.ledger.BytesValue; | import com.jd.blockchain.ledger.BytesValue; | ||||
import com.jd.blockchain.ledger.CryptoSetting; | import com.jd.blockchain.ledger.CryptoSetting; | ||||
import com.jd.blockchain.ledger.MerkleProof; | |||||
import com.jd.blockchain.storage.service.ExPolicyKVStorage; | import com.jd.blockchain.storage.service.ExPolicyKVStorage; | ||||
import com.jd.blockchain.storage.service.VersioningKVStorage; | import com.jd.blockchain.storage.service.VersioningKVStorage; | ||||
import com.jd.blockchain.utils.Bytes; | import com.jd.blockchain.utils.Bytes; | ||||
@@ -64,13 +65,13 @@ public class BaseAccount implements AccountHeader, MerkleProvable, Transactional | |||||
/** | /** | ||||
* Create a account instance with the specified address and pubkey and load it's | * Create a account instance with the specified address and pubkey and load it's | ||||
* merkle dataset with the specified root hash. which is used for storing data | |||||
* merkle dataset from the specified root hash. This merkle dateset is used for storing data | |||||
* of this account.<br> | * of this account.<br> | ||||
* | * | ||||
* @param address | * @param address | ||||
* @param pubKey | * @param pubKey | ||||
* @param dataRootHash merkle root hash of account's data; if null be set, | |||||
* create a new empty merkle dataset; | |||||
* @param dataRootHash merkle root hash of account's data; if set to a null value, | |||||
* an empty merkle dataset is created; | |||||
* @param cryptoSetting | * @param cryptoSetting | ||||
* @param exStorage | * @param exStorage | ||||
* @param verStorage | * @param verStorage | ||||
@@ -1,21 +0,0 @@ | |||||
package com.jd.blockchain.ledger.core; | |||||
/** | |||||
* @author hhq | |||||
* @version 1.0 | |||||
* @created 14-6��-2018 12:13:32 | |||||
*/ | |||||
public class Consensus { | |||||
public P2PRealm m_P2PRealm; | |||||
public Consensus(){ | |||||
} | |||||
public void finalize() throws Throwable { | |||||
} | |||||
} |
@@ -2,10 +2,10 @@ package com.jd.blockchain.ledger.core; | |||||
import com.jd.blockchain.crypto.HashDigest; | import com.jd.blockchain.crypto.HashDigest; | ||||
import com.jd.blockchain.crypto.PubKey; | import com.jd.blockchain.crypto.PubKey; | ||||
import com.jd.blockchain.ledger.AccountHeader; | |||||
import com.jd.blockchain.ledger.BytesValue; | |||||
import com.jd.blockchain.ledger.BytesData; | import com.jd.blockchain.ledger.BytesData; | ||||
import com.jd.blockchain.ledger.BytesValue; | |||||
import com.jd.blockchain.ledger.ContractInfo; | import com.jd.blockchain.ledger.ContractInfo; | ||||
import com.jd.blockchain.ledger.MerkleProof; | |||||
import com.jd.blockchain.utils.Bytes; | import com.jd.blockchain.utils.Bytes; | ||||
public class ContractAccount implements ContractInfo { | public class ContractAccount implements ContractInfo { | ||||
@@ -0,0 +1,29 @@ | |||||
package com.jd.blockchain.ledger.core; | |||||
import com.jd.blockchain.crypto.HashDigest; | |||||
import com.jd.blockchain.ledger.AccountHeader; | |||||
import com.jd.blockchain.ledger.MerkleProof; | |||||
import com.jd.blockchain.utils.Bytes; | |||||
public interface ContractAccountQuery { | |||||
AccountHeader[] getAccounts(int fromIndex, int count); | |||||
HashDigest getRootHash(); | |||||
/** | |||||
* 返回合约总数; | |||||
* | |||||
* @return | |||||
*/ | |||||
long getTotalCount(); | |||||
MerkleProof getProof(Bytes address); | |||||
boolean contains(Bytes address); | |||||
ContractAccount getContract(Bytes address); | |||||
ContractAccount getContract(Bytes address, long version); | |||||
} |
@@ -5,12 +5,13 @@ import com.jd.blockchain.crypto.PubKey; | |||||
import com.jd.blockchain.ledger.AccountHeader; | import com.jd.blockchain.ledger.AccountHeader; | ||||
import com.jd.blockchain.ledger.CryptoSetting; | import com.jd.blockchain.ledger.CryptoSetting; | ||||
import com.jd.blockchain.ledger.DigitalSignature; | import com.jd.blockchain.ledger.DigitalSignature; | ||||
import com.jd.blockchain.ledger.MerkleProof; | |||||
import com.jd.blockchain.storage.service.ExPolicyKVStorage; | import com.jd.blockchain.storage.service.ExPolicyKVStorage; | ||||
import com.jd.blockchain.storage.service.VersioningKVStorage; | import com.jd.blockchain.storage.service.VersioningKVStorage; | ||||
import com.jd.blockchain.utils.Bytes; | import com.jd.blockchain.utils.Bytes; | ||||
import com.jd.blockchain.utils.Transactional; | import com.jd.blockchain.utils.Transactional; | ||||
public class ContractAccountSet implements MerkleProvable, Transactional { | |||||
public class ContractAccountSet implements MerkleProvable, Transactional, ContractAccountQuery { | |||||
private AccountSet accountSet; | private AccountSet accountSet; | ||||
@@ -25,6 +26,7 @@ public class ContractAccountSet implements MerkleProvable, Transactional { | |||||
accountSet = new AccountSet(dataRootHash, cryptoSetting, prefix, exStorage, verStorage, readonly, accessPolicy); | accountSet = new AccountSet(dataRootHash, cryptoSetting, prefix, exStorage, verStorage, readonly, accessPolicy); | ||||
} | } | ||||
@Override | |||||
public AccountHeader[] getAccounts(int fromIndex, int count) { | public AccountHeader[] getAccounts(int fromIndex, int count) { | ||||
return accountSet.getAccounts(fromIndex,count); | return accountSet.getAccounts(fromIndex,count); | ||||
} | } | ||||
@@ -33,6 +35,10 @@ public class ContractAccountSet implements MerkleProvable, Transactional { | |||||
return accountSet.isReadonly(); | return accountSet.isReadonly(); | ||||
} | } | ||||
void setReadonly() { | |||||
accountSet.setReadonly(); | |||||
} | |||||
@Override | @Override | ||||
public HashDigest getRootHash() { | public HashDigest getRootHash() { | ||||
return accountSet.getRootHash(); | return accountSet.getRootHash(); | ||||
@@ -43,6 +49,7 @@ public class ContractAccountSet implements MerkleProvable, Transactional { | |||||
* | * | ||||
* @return | * @return | ||||
*/ | */ | ||||
@Override | |||||
public long getTotalCount() { | public long getTotalCount() { | ||||
return accountSet.getTotalCount(); | return accountSet.getTotalCount(); | ||||
} | } | ||||
@@ -52,15 +59,18 @@ public class ContractAccountSet implements MerkleProvable, Transactional { | |||||
return accountSet.getProof(address); | return accountSet.getProof(address); | ||||
} | } | ||||
@Override | |||||
public boolean contains(Bytes address) { | public boolean contains(Bytes address) { | ||||
return accountSet.contains(address); | return accountSet.contains(address); | ||||
} | } | ||||
@Override | |||||
public ContractAccount getContract(Bytes address) { | public ContractAccount getContract(Bytes address) { | ||||
BaseAccount accBase = accountSet.getAccount(address); | BaseAccount accBase = accountSet.getAccount(address); | ||||
return new ContractAccount(accBase); | return new ContractAccount(accBase); | ||||
} | } | ||||
@Override | |||||
public ContractAccount getContract(Bytes address, long version) { | public ContractAccount getContract(Bytes address, long version) { | ||||
BaseAccount accBase = accountSet.getAccount(address, version); | BaseAccount accBase = accountSet.getAccount(address, version); | ||||
return new ContractAccount(accBase); | return new ContractAccount(accBase); | ||||
@@ -82,7 +82,7 @@ public class CryptoConfig implements CryptoSetting { | |||||
public void setHashAlgorithm(short hashAlgorithm) { | public void setHashAlgorithm(short hashAlgorithm) { | ||||
if (codeAlgorithms == null || !codeAlgorithms.containsKey(hashAlgorithm)) { | if (codeAlgorithms == null || !codeAlgorithms.containsKey(hashAlgorithm)) { | ||||
throw new LedgerException("The specified algorithm[" + hashAlgorithm + "] has no provider!"); | |||||
throw new LedgerException("Current CryptoConfig has no crypto provider!"); | |||||
} | } | ||||
this.hashAlgorithm = hashAlgorithm; | this.hashAlgorithm = hashAlgorithm; | ||||
} | } | ||||
@@ -8,6 +8,7 @@ import com.jd.blockchain.ledger.BytesData; | |||||
import com.jd.blockchain.ledger.BytesValue; | import com.jd.blockchain.ledger.BytesValue; | ||||
import com.jd.blockchain.ledger.KVDataEntry; | import com.jd.blockchain.ledger.KVDataEntry; | ||||
import com.jd.blockchain.ledger.KVDataObject; | import com.jd.blockchain.ledger.KVDataObject; | ||||
import com.jd.blockchain.ledger.MerkleProof; | |||||
import com.jd.blockchain.utils.Bytes; | import com.jd.blockchain.utils.Bytes; | ||||
public class DataAccount implements AccountHeader, MerkleProvable { | public class DataAccount implements AccountHeader, MerkleProvable { | ||||
@@ -0,0 +1,32 @@ | |||||
package com.jd.blockchain.ledger.core; | |||||
import com.jd.blockchain.crypto.HashDigest; | |||||
import com.jd.blockchain.ledger.AccountHeader; | |||||
import com.jd.blockchain.ledger.MerkleProof; | |||||
import com.jd.blockchain.utils.Bytes; | |||||
public interface DataAccountQuery { | |||||
AccountHeader[] getAccounts(int fromIndex, int count); | |||||
HashDigest getRootHash(); | |||||
long getTotalCount(); | |||||
/** | |||||
* 返回账户的存在性证明; | |||||
*/ | |||||
MerkleProof getProof(Bytes address); | |||||
/** | |||||
* 返回数据账户; <br> | |||||
* 如果不存在,则返回 null; | |||||
* | |||||
* @param address | |||||
* @return | |||||
*/ | |||||
DataAccount getDataAccount(Bytes address); | |||||
DataAccount getDataAccount(Bytes address, long version); | |||||
} |
@@ -5,12 +5,13 @@ import com.jd.blockchain.crypto.PubKey; | |||||
import com.jd.blockchain.ledger.AccountHeader; | import com.jd.blockchain.ledger.AccountHeader; | ||||
import com.jd.blockchain.ledger.CryptoSetting; | import com.jd.blockchain.ledger.CryptoSetting; | ||||
import com.jd.blockchain.ledger.DigitalSignature; | import com.jd.blockchain.ledger.DigitalSignature; | ||||
import com.jd.blockchain.ledger.MerkleProof; | |||||
import com.jd.blockchain.storage.service.ExPolicyKVStorage; | import com.jd.blockchain.storage.service.ExPolicyKVStorage; | ||||
import com.jd.blockchain.storage.service.VersioningKVStorage; | import com.jd.blockchain.storage.service.VersioningKVStorage; | ||||
import com.jd.blockchain.utils.Bytes; | import com.jd.blockchain.utils.Bytes; | ||||
import com.jd.blockchain.utils.Transactional; | import com.jd.blockchain.utils.Transactional; | ||||
public class DataAccountSet implements MerkleProvable, Transactional { | |||||
public class DataAccountSet implements MerkleProvable, Transactional, DataAccountQuery { | |||||
private AccountSet accountSet; | private AccountSet accountSet; | ||||
@@ -25,6 +26,7 @@ public class DataAccountSet implements MerkleProvable, Transactional { | |||||
accountSet = new AccountSet(dataRootHash, cryptoSetting, prefix, exStorage, verStorage, readonly, accessPolicy); | accountSet = new AccountSet(dataRootHash, cryptoSetting, prefix, exStorage, verStorage, readonly, accessPolicy); | ||||
} | } | ||||
@Override | |||||
public AccountHeader[] getAccounts(int fromIndex, int count) { | public AccountHeader[] getAccounts(int fromIndex, int count) { | ||||
return accountSet.getAccounts(fromIndex, count); | return accountSet.getAccounts(fromIndex, count); | ||||
} | } | ||||
@@ -33,11 +35,16 @@ public class DataAccountSet implements MerkleProvable, Transactional { | |||||
return accountSet.isReadonly(); | return accountSet.isReadonly(); | ||||
} | } | ||||
void setReadonly() { | |||||
accountSet.setReadonly(); | |||||
} | |||||
@Override | @Override | ||||
public HashDigest getRootHash() { | public HashDigest getRootHash() { | ||||
return accountSet.getRootHash(); | return accountSet.getRootHash(); | ||||
} | } | ||||
@Override | |||||
public long getTotalCount() { | public long getTotalCount() { | ||||
return accountSet.getTotalCount(); | return accountSet.getTotalCount(); | ||||
} | } | ||||
@@ -63,6 +70,7 @@ public class DataAccountSet implements MerkleProvable, Transactional { | |||||
* @param address | * @param address | ||||
* @return | * @return | ||||
*/ | */ | ||||
@Override | |||||
public DataAccount getDataAccount(Bytes address) { | public DataAccount getDataAccount(Bytes address) { | ||||
BaseAccount accBase = accountSet.getAccount(address); | BaseAccount accBase = accountSet.getAccount(address); | ||||
if (accBase == null) { | if (accBase == null) { | ||||
@@ -71,6 +79,7 @@ public class DataAccountSet implements MerkleProvable, Transactional { | |||||
return new DataAccount(accBase); | return new DataAccount(accBase); | ||||
} | } | ||||
@Override | |||||
public DataAccount getDataAccount(Bytes address, long version) { | public DataAccount getDataAccount(Bytes address, long version) { | ||||
BaseAccount accBase = accountSet.getAccount(address, version); | BaseAccount accBase = accountSet.getAccount(address, version); | ||||
return new DataAccount(accBase); | return new DataAccount(accBase); | ||||
@@ -0,0 +1,132 @@ | |||||
package com.jd.blockchain.ledger.core; | |||||
import java.util.ArrayList; | |||||
import java.util.HashMap; | |||||
import java.util.List; | |||||
import java.util.Map; | |||||
import java.util.concurrent.ConcurrentHashMap; | |||||
import org.springframework.stereotype.Component; | |||||
import com.jd.blockchain.ledger.LedgerException; | |||||
import com.jd.blockchain.ledger.Operation; | |||||
import com.jd.blockchain.ledger.core.handles.ContractCodeDeployOperationHandle; | |||||
import com.jd.blockchain.ledger.core.handles.DataAccountKVSetOperationHandle; | |||||
import com.jd.blockchain.ledger.core.handles.DataAccountRegisterOperationHandle; | |||||
import com.jd.blockchain.ledger.core.handles.JVMContractEventSendOperationHandle; | |||||
import com.jd.blockchain.ledger.core.handles.LedgerInitOperationHandle; | |||||
import com.jd.blockchain.ledger.core.handles.RolesConfigureOperationHandle; | |||||
import com.jd.blockchain.ledger.core.handles.UserAuthorizeOperationHandle; | |||||
import com.jd.blockchain.ledger.core.handles.UserRegisterOperationHandle; | |||||
import com.jd.blockchain.transaction.ContractCodeDeployOpTemplate; | |||||
import com.jd.blockchain.transaction.ContractEventSendOpTemplate; | |||||
import com.jd.blockchain.transaction.DataAccountKVSetOpTemplate; | |||||
import com.jd.blockchain.transaction.DataAccountRegisterOpTemplate; | |||||
import com.jd.blockchain.transaction.LedgerInitOpTemplate; | |||||
import com.jd.blockchain.transaction.RolesConfigureOpTemplate; | |||||
import com.jd.blockchain.transaction.UserAuthorizeOpTemplate; | |||||
import com.jd.blockchain.transaction.UserRegisterOpTemplate; | |||||
@Component | |||||
public class DefaultOperationHandleRegisteration implements OperationHandleRegisteration { | |||||
private static Map<Class<?>, OperationHandle> DEFAULT_HANDLES = new HashMap<>(); | |||||
private Map<Class<?>, OperationHandle> handles = new ConcurrentHashMap<>(); | |||||
static { | |||||
registerDefaultHandle(new LedgerInitOperationHandle()); | |||||
registerDefaultHandle(new RolesConfigureOperationHandle()); | |||||
registerDefaultHandle(new UserAuthorizeOperationHandle()); | |||||
registerDefaultHandle(new UserRegisterOperationHandle()); | |||||
registerDefaultHandle(new DataAccountKVSetOperationHandle()); | |||||
registerDefaultHandle(new DataAccountRegisterOperationHandle()); | |||||
registerDefaultHandle(new ContractCodeDeployOperationHandle()); | |||||
registerDefaultHandle(new JVMContractEventSendOperationHandle()); | |||||
} | |||||
private static void registerDefaultHandle(OperationHandle handle) { | |||||
DEFAULT_HANDLES.put(handle.getOperationType(), handle); | |||||
} | |||||
/** | |||||
* 注册操作处理器;此方法将覆盖默认的操作处理器配置; | |||||
* | |||||
* @param handle | |||||
*/ | |||||
public void registerHandle(OperationHandle handle) { | |||||
List<Class<?>> opTypes = new ArrayList<Class<?>>(); | |||||
for (Class<?> opType : handles.keySet()) { | |||||
if (opType.isAssignableFrom(handle.getOperationType())) { | |||||
opTypes.add(opType); | |||||
} | |||||
} | |||||
for (Class<?> opType : opTypes) { | |||||
handles.put(opType, handle); | |||||
} | |||||
handles.put(handle.getOperationType(), handle); | |||||
} | |||||
private OperationHandle getRegisteredHandle(Class<?> operationType) { | |||||
OperationHandle hdl = handles.get(operationType); | |||||
if (hdl == null) { | |||||
hdl = DEFAULT_HANDLES.get(operationType); | |||||
//按“操作类型”的继承关系匹配; | |||||
if (hdl == null) { | |||||
for (Class<?> opType : handles.keySet()) { | |||||
if (opType.isAssignableFrom(operationType)) { | |||||
hdl = handles.get(opType); | |||||
break; | |||||
} | |||||
} | |||||
} | |||||
if (hdl == null) { | |||||
for (Class<?> opType : DEFAULT_HANDLES.keySet()) { | |||||
if (opType.isAssignableFrom(operationType)) { | |||||
hdl = DEFAULT_HANDLES.get(opType); | |||||
break; | |||||
} | |||||
} | |||||
} | |||||
if (hdl != null) { | |||||
handles.put(operationType, hdl); | |||||
} | |||||
} | |||||
return hdl; | |||||
} | |||||
/* | |||||
* (non-Javadoc) | |||||
* | |||||
* @see | |||||
* com.jd.blockchain.ledger.core.impl.OperationHandleRegisteration#getHandle( | |||||
* java.lang.Class) | |||||
*/ | |||||
@Override | |||||
public OperationHandle getHandle(Class<? extends Operation> operationType) { | |||||
OperationHandle hdl = getRegisteredHandle(operationType); | |||||
if (hdl == null) { | |||||
throw new LedgerException("Unsupported operation type[" + operationType.getName() + "]!"); | |||||
} | |||||
return hdl; | |||||
} | |||||
private static class OpHandleStub { | |||||
private Class<? extends Operation> operationType; | |||||
private OperationHandle operationHandle; | |||||
} | |||||
} |
@@ -0,0 +1,209 @@ | |||||
package com.jd.blockchain.ledger.core; | |||||
import com.jd.blockchain.crypto.HashDigest; | |||||
import com.jd.blockchain.ledger.AccountHeader; | |||||
import com.jd.blockchain.ledger.LedgerAdminInfo; | |||||
import com.jd.blockchain.ledger.MerkleProof; | |||||
import com.jd.blockchain.ledger.ParticipantDataQuery; | |||||
import com.jd.blockchain.ledger.ParticipantNode; | |||||
import com.jd.blockchain.utils.Bytes; | |||||
public class EmptyLedgerDataset implements LedgerDataQuery { | |||||
private static final LedgerAdminDataQuery EMPTY_ADMIN_DATA = new EmptyAdminData(); | |||||
private static final UserAccountQuery EMPTY_USER_ACCOUNTS = new EmptyUserAccountSet(); | |||||
private static final DataAccountQuery EMPTY_DATA_ACCOUNTS = new EmptyDataAccountSet(); | |||||
private static final ContractAccountQuery EMPTY_CONTRACT_ACCOUNTS = new EmptyContractAccountSet(); | |||||
private static final ParticipantDataQuery EMPTY_PARTICIPANTS = new EmptyParticipantData(); | |||||
@Override | |||||
public LedgerAdminDataQuery getAdminDataset() { | |||||
return EMPTY_ADMIN_DATA; | |||||
} | |||||
@Override | |||||
public UserAccountQuery getUserAccountSet() { | |||||
return EMPTY_USER_ACCOUNTS; | |||||
} | |||||
@Override | |||||
public DataAccountQuery getDataAccountSet() { | |||||
return EMPTY_DATA_ACCOUNTS; | |||||
} | |||||
@Override | |||||
public ContractAccountQuery getContractAccountset() { | |||||
return EMPTY_CONTRACT_ACCOUNTS; | |||||
} | |||||
private static class EmptyAdminData implements LedgerAdminDataQuery{ | |||||
@Override | |||||
public LedgerAdminInfo getAdminInfo() { | |||||
return null; | |||||
} | |||||
@Override | |||||
public ParticipantDataQuery getParticipantDataset() { | |||||
return EMPTY_PARTICIPANTS; | |||||
} | |||||
} | |||||
private static class EmptyParticipantData implements ParticipantDataQuery{ | |||||
@Override | |||||
public HashDigest getRootHash() { | |||||
return null; | |||||
} | |||||
@Override | |||||
public MerkleProof getProof(Bytes key) { | |||||
return null; | |||||
} | |||||
@Override | |||||
public long getParticipantCount() { | |||||
return 0; | |||||
} | |||||
@Override | |||||
public boolean contains(Bytes address) { | |||||
return false; | |||||
} | |||||
@Override | |||||
public ParticipantNode getParticipant(Bytes address) { | |||||
return null; | |||||
} | |||||
@Override | |||||
public ParticipantNode[] getParticipants() { | |||||
return null; | |||||
} | |||||
} | |||||
private static class EmptyUserAccountSet implements UserAccountQuery{ | |||||
@Override | |||||
public AccountHeader[] getAccounts(int fromIndex, int count) { | |||||
return null; | |||||
} | |||||
@Override | |||||
public long getTotalCount() { | |||||
return 0; | |||||
} | |||||
@Override | |||||
public HashDigest getRootHash() { | |||||
return null; | |||||
} | |||||
@Override | |||||
public MerkleProof getProof(Bytes key) { | |||||
return null; | |||||
} | |||||
@Override | |||||
public UserAccount getUser(String address) { | |||||
return null; | |||||
} | |||||
@Override | |||||
public UserAccount getUser(Bytes address) { | |||||
return null; | |||||
} | |||||
@Override | |||||
public boolean contains(Bytes address) { | |||||
return false; | |||||
} | |||||
@Override | |||||
public UserAccount getUser(Bytes address, long version) { | |||||
return null; | |||||
} | |||||
} | |||||
private static class EmptyDataAccountSet implements DataAccountQuery{ | |||||
@Override | |||||
public AccountHeader[] getAccounts(int fromIndex, int count) { | |||||
return null; | |||||
} | |||||
@Override | |||||
public HashDigest getRootHash() { | |||||
return null; | |||||
} | |||||
@Override | |||||
public long getTotalCount() { | |||||
return 0; | |||||
} | |||||
@Override | |||||
public MerkleProof getProof(Bytes address) { | |||||
return null; | |||||
} | |||||
@Override | |||||
public DataAccount getDataAccount(Bytes address) { | |||||
return null; | |||||
} | |||||
@Override | |||||
public DataAccount getDataAccount(Bytes address, long version) { | |||||
return null; | |||||
} | |||||
} | |||||
private static class EmptyContractAccountSet implements ContractAccountQuery{ | |||||
@Override | |||||
public AccountHeader[] getAccounts(int fromIndex, int count) { | |||||
return null; | |||||
} | |||||
@Override | |||||
public HashDigest getRootHash() { | |||||
return null; | |||||
} | |||||
@Override | |||||
public long getTotalCount() { | |||||
return 0; | |||||
} | |||||
@Override | |||||
public MerkleProof getProof(Bytes address) { | |||||
return null; | |||||
} | |||||
@Override | |||||
public boolean contains(Bytes address) { | |||||
return false; | |||||
} | |||||
@Override | |||||
public ContractAccount getContract(Bytes address) { | |||||
return null; | |||||
} | |||||
@Override | |||||
public ContractAccount getContract(Bytes address, long version) { | |||||
return null; | |||||
} | |||||
} | |||||
} |
@@ -0,0 +1,98 @@ | |||||
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.utils.Bytes; | |||||
class FullPermissionedSecurityManager implements LedgerSecurityManager { | |||||
public static final FullPermissionedSecurityManager INSTANCE = new FullPermissionedSecurityManager(); | |||||
@Override | |||||
public SecurityPolicy createSecurityPolicy(Set<Bytes> endpoints, Set<Bytes> nodes) { | |||||
return new FullPermissionedPolicy(endpoints, nodes); | |||||
} | |||||
private static class FullPermissionedPolicy implements SecurityPolicy { | |||||
private Set<Bytes> endpoints; | |||||
private Set<Bytes> nodes; | |||||
public FullPermissionedPolicy(Set<Bytes> endpoints, Set<Bytes> nodes) { | |||||
this.endpoints = endpoints; | |||||
this.nodes = nodes; | |||||
} | |||||
@Override | |||||
public Set<Bytes> getEndpoints() { | |||||
return endpoints; | |||||
} | |||||
@Override | |||||
public Set<Bytes> getNodes() { | |||||
return nodes; | |||||
} | |||||
@Override | |||||
public boolean isEndpointEnable(LedgerPermission permission, MultiIDsPolicy midPolicy) { | |||||
return true; | |||||
} | |||||
@Override | |||||
public boolean isEndpointEnable(TransactionPermission permission, MultiIDsPolicy midPolicy) { | |||||
return true; | |||||
} | |||||
@Override | |||||
public boolean isNodeEnable(LedgerPermission permission, MultiIDsPolicy midPolicy) { | |||||
return true; | |||||
} | |||||
@Override | |||||
public boolean isNodeEnable(TransactionPermission permission, MultiIDsPolicy midPolicy) { | |||||
return true; | |||||
} | |||||
@Override | |||||
public void checkEndpointPermission(LedgerPermission permission, MultiIDsPolicy midPolicy) | |||||
throws LedgerSecurityException { | |||||
} | |||||
@Override | |||||
public void checkEndpointPermission(TransactionPermission permission, MultiIDsPolicy midPolicy) | |||||
throws LedgerSecurityException { | |||||
} | |||||
@Override | |||||
public void checkNodePermission(LedgerPermission permission, MultiIDsPolicy midPolicy) throws LedgerSecurityException { | |||||
} | |||||
@Override | |||||
public void checkNodePermission(TransactionPermission permission, MultiIDsPolicy midPolicy) | |||||
throws LedgerSecurityException { | |||||
} | |||||
@Override | |||||
public boolean isEndpointValid(MultiIDsPolicy midPolicy) { | |||||
return true; | |||||
} | |||||
@Override | |||||
public boolean isNodeValid(MultiIDsPolicy midPolicy) { | |||||
return true; | |||||
} | |||||
@Override | |||||
public void checkEndpointValidity(MultiIDsPolicy midPolicy) throws LedgerSecurityException { | |||||
} | |||||
@Override | |||||
public void checkNodeValidity(MultiIDsPolicy midPolicy) throws LedgerSecurityException { | |||||
} | |||||
} | |||||
} |
@@ -1,22 +0,0 @@ | |||||
package com.jd.blockchain.ledger.core; | |||||
import com.jd.blockchain.ledger.ParticipantNode; | |||||
/** | |||||
* @author hhq | |||||
* @version 1.0 | |||||
* @created 14-6��-2018 12:13:32 | |||||
*/ | |||||
public class Gateway extends Node { | |||||
public ParticipantNode m_Participant; | |||||
public Gateway(){ | |||||
} | |||||
public void finalize() throws Throwable { | |||||
super.finalize(); | |||||
} | |||||
} |
@@ -1,3 +1,4 @@ | |||||
package com.jd.blockchain.ledger.core; | |||||
//package com.jd.blockchain.ledger.core.impl; | //package com.jd.blockchain.ledger.core.impl; | ||||
// | // | ||||
//import com.jd.blockchain.storage.service.ExPolicyKVStorage; | //import com.jd.blockchain.storage.service.ExPolicyKVStorage; |
@@ -0,0 +1,12 @@ | |||||
package com.jd.blockchain.ledger.core; | |||||
import com.jd.blockchain.ledger.LedgerAdminInfo; | |||||
import com.jd.blockchain.ledger.ParticipantDataQuery; | |||||
public interface LedgerAdminDataQuery { | |||||
LedgerAdminInfo getAdminInfo(); | |||||
ParticipantDataQuery getParticipantDataset(); | |||||
} |
@@ -0,0 +1,469 @@ | |||||
package com.jd.blockchain.ledger.core; | |||||
import org.slf4j.Logger; | |||||
import org.slf4j.LoggerFactory; | |||||
import com.jd.blockchain.binaryproto.BinaryProtocol; | |||||
import com.jd.blockchain.binaryproto.DataContractRegistry; | |||||
import com.jd.blockchain.crypto.Crypto; | |||||
import com.jd.blockchain.crypto.HashDigest; | |||||
import com.jd.blockchain.crypto.HashFunction; | |||||
import com.jd.blockchain.ledger.LedgerAdminInfo; | |||||
import com.jd.blockchain.ledger.LedgerException; | |||||
import com.jd.blockchain.ledger.LedgerInitSetting; | |||||
import com.jd.blockchain.ledger.LedgerMetadata; | |||||
import com.jd.blockchain.ledger.LedgerMetadata_V2; | |||||
import com.jd.blockchain.ledger.LedgerSettings; | |||||
import com.jd.blockchain.ledger.ParticipantNode; | |||||
import com.jd.blockchain.ledger.RolePrivilegeSettings; | |||||
import com.jd.blockchain.ledger.UserRolesSettings; | |||||
import com.jd.blockchain.storage.service.ExPolicyKVStorage; | |||||
import com.jd.blockchain.storage.service.ExPolicyKVStorage.ExPolicy; | |||||
import com.jd.blockchain.storage.service.VersioningKVStorage; | |||||
import com.jd.blockchain.utils.Bytes; | |||||
import com.jd.blockchain.utils.Transactional; | |||||
public class LedgerAdminDataset implements Transactional, LedgerAdminDataQuery, LedgerAdminInfo { | |||||
static { | |||||
DataContractRegistry.register(LedgerMetadata.class); | |||||
DataContractRegistry.register(LedgerMetadata_V2.class); | |||||
} | |||||
private static Logger LOGGER = LoggerFactory.getLogger(LedgerAdminDataset.class); | |||||
public static final String LEDGER_META_PREFIX = "MTA" + LedgerConsts.KEY_SEPERATOR; | |||||
public static final String LEDGER_PARTICIPANT_PREFIX = "PAR" + LedgerConsts.KEY_SEPERATOR; | |||||
public static final String LEDGER_SETTING_PREFIX = "SET" + LedgerConsts.KEY_SEPERATOR; | |||||
public static final String ROLE_PRIVILEGE_PREFIX = "RPV" + LedgerConsts.KEY_SEPERATOR; | |||||
public static final String USER_ROLE_PREFIX = "URO" + LedgerConsts.KEY_SEPERATOR; | |||||
private final Bytes metaPrefix; | |||||
private final Bytes settingPrefix; | |||||
private LedgerMetadata_V2 origMetadata; | |||||
private LedgerMetadataInfo metadata; | |||||
/** | |||||
* 原来的账本设置; | |||||
* | |||||
* <br> | |||||
* 对 LedgerMetadata 修改的新配置不能立即生效,需要达成共识后,在下一次区块计算中才生效; | |||||
*/ | |||||
private LedgerSettings previousSettings; | |||||
private HashDigest previousSettingHash; | |||||
/** | |||||
* 账本的参与节点; | |||||
*/ | |||||
private ParticipantDataset participants; | |||||
/** | |||||
* “角色-权限”数据集; | |||||
*/ | |||||
private RolePrivilegeDataset rolePrivileges; | |||||
/** | |||||
* “用户-角色”数据集; | |||||
*/ | |||||
private UserRoleDataset userRoles; | |||||
/** | |||||
* 账本参数配置; | |||||
*/ | |||||
private LedgerSettings settings; | |||||
private ExPolicyKVStorage storage; | |||||
private HashDigest adminDataHash; | |||||
private boolean readonly; | |||||
private boolean updated; | |||||
public HashDigest getHash() { | |||||
return adminDataHash; | |||||
} | |||||
public boolean isReadonly() { | |||||
return readonly; | |||||
} | |||||
void setReadonly() { | |||||
this.readonly = true; | |||||
} | |||||
public LedgerSettings getPreviousSetting() { | |||||
return previousSettings; | |||||
} | |||||
@Override | |||||
public RolePrivilegeSettings getRolePrivileges() { | |||||
return rolePrivileges; | |||||
} | |||||
@Override | |||||
public UserRolesSettings getUserRoles() { | |||||
return userRoles; | |||||
} | |||||
@Override | |||||
public LedgerAdminInfo getAdminInfo() { | |||||
return this; | |||||
} | |||||
/** | |||||
* 初始化账本的管理账户; | |||||
* | |||||
* <br> | |||||
* | |||||
* 只在新建账本时调用此方法; | |||||
* | |||||
* @param ledgerSeed | |||||
* @param settings | |||||
* @param partiList | |||||
* @param exPolicyStorage | |||||
* @param versioningStorage | |||||
*/ | |||||
public LedgerAdminDataset(LedgerInitSetting initSetting, String keyPrefix, ExPolicyKVStorage exPolicyStorage, | |||||
VersioningKVStorage versioningStorage) { | |||||
this.metaPrefix = Bytes.fromString(keyPrefix + LEDGER_META_PREFIX); | |||||
this.settingPrefix = Bytes.fromString(keyPrefix + LEDGER_SETTING_PREFIX); | |||||
ParticipantNode[] parties = initSetting.getConsensusParticipants(); | |||||
if (parties.length == 0) { | |||||
throw new LedgerException("No participant!"); | |||||
} | |||||
// 初始化元数据; | |||||
this.metadata = new LedgerMetadataInfo(); | |||||
this.metadata.setSeed(initSetting.getLedgerSeed()); | |||||
// 新配置; | |||||
this.settings = new LedgerConfiguration(initSetting.getConsensusProvider(), initSetting.getConsensusSettings(), | |||||
initSetting.getCryptoSetting()); | |||||
this.previousSettings = new LedgerConfiguration(settings); | |||||
this.previousSettingHash = null; | |||||
this.adminDataHash = null; | |||||
// 基于原配置初始化参与者列表; | |||||
String partiPrefix = keyPrefix + LEDGER_PARTICIPANT_PREFIX; | |||||
this.participants = new ParticipantDataset(previousSettings.getCryptoSetting(), partiPrefix, exPolicyStorage, | |||||
versioningStorage); | |||||
for (ParticipantNode p : parties) { | |||||
this.participants.addConsensusParticipant(p); | |||||
} | |||||
String rolePrivilegePrefix = keyPrefix + ROLE_PRIVILEGE_PREFIX; | |||||
this.rolePrivileges = new RolePrivilegeDataset(this.settings.getCryptoSetting(), rolePrivilegePrefix, | |||||
exPolicyStorage, versioningStorage); | |||||
String userRolePrefix = keyPrefix + USER_ROLE_PREFIX; | |||||
this.userRoles = new UserRoleDataset(this.settings.getCryptoSetting(), userRolePrefix, exPolicyStorage, | |||||
versioningStorage); | |||||
// 初始化其它属性; | |||||
this.storage = exPolicyStorage; | |||||
this.readonly = false; | |||||
} | |||||
public LedgerAdminDataset(HashDigest adminAccountHash, String keyPrefix, ExPolicyKVStorage kvStorage, | |||||
VersioningKVStorage versioningKVStorage, boolean readonly) { | |||||
this.metaPrefix = Bytes.fromString(keyPrefix + LEDGER_META_PREFIX); | |||||
this.settingPrefix = Bytes.fromString(keyPrefix + LEDGER_SETTING_PREFIX); | |||||
this.storage = kvStorage; | |||||
this.readonly = readonly; | |||||
this.origMetadata = loadAndVerifyMetadata(adminAccountHash); | |||||
this.metadata = new LedgerMetadataInfo(origMetadata); | |||||
this.settings = loadAndVerifySettings(metadata.getSettingsHash()); | |||||
// 复制记录一份配置作为上一个区块的原始配置,该实例仅供读取,不做修改,也不会回写到存储; | |||||
this.previousSettings = new LedgerConfiguration(settings); | |||||
this.previousSettingHash = metadata.getSettingsHash(); | |||||
this.adminDataHash = adminAccountHash; | |||||
String partiPrefix = keyPrefix + LEDGER_PARTICIPANT_PREFIX; | |||||
this.participants = new ParticipantDataset(metadata.getParticipantsHash(), previousSettings.getCryptoSetting(), | |||||
partiPrefix, kvStorage, versioningKVStorage, readonly); | |||||
String rolePrivilegePrefix = keyPrefix + ROLE_PRIVILEGE_PREFIX; | |||||
this.rolePrivileges = new RolePrivilegeDataset(metadata.getRolePrivilegesHash(), | |||||
previousSettings.getCryptoSetting(), rolePrivilegePrefix, kvStorage, versioningKVStorage, readonly); | |||||
String userRolePrefix = keyPrefix + USER_ROLE_PREFIX; | |||||
this.userRoles = new UserRoleDataset(metadata.getUserRolesHash(), previousSettings.getCryptoSetting(), | |||||
userRolePrefix, kvStorage, versioningKVStorage, readonly); | |||||
} | |||||
private LedgerSettings loadAndVerifySettings(HashDigest settingsHash) { | |||||
if (settingsHash == null) { | |||||
return null; | |||||
} | |||||
Bytes key = encodeSettingsKey(settingsHash); | |||||
byte[] bytes = storage.get(key); | |||||
HashFunction hashFunc = Crypto.getHashFunction(settingsHash.getAlgorithm()); | |||||
if (!hashFunc.verify(settingsHash, bytes)) { | |||||
String errorMsg = "Verification of the hash for ledger setting failed! --[HASH=" + key + "]"; | |||||
LOGGER.error(errorMsg); | |||||
throw new LedgerException(errorMsg); | |||||
} | |||||
return deserializeSettings(bytes); | |||||
} | |||||
private LedgerSettings deserializeSettings(byte[] bytes) { | |||||
return BinaryProtocol.decode(bytes); | |||||
} | |||||
private byte[] serializeSetting(LedgerSettings setting) { | |||||
return BinaryProtocol.encode(setting, LedgerSettings.class); | |||||
} | |||||
private LedgerMetadata_V2 loadAndVerifyMetadata(HashDigest adminAccountHash) { | |||||
Bytes key = encodeMetadataKey(adminAccountHash); | |||||
byte[] bytes = storage.get(key); | |||||
HashFunction hashFunc = Crypto.getHashFunction(adminAccountHash.getAlgorithm()); | |||||
if (!hashFunc.verify(adminAccountHash, bytes)) { | |||||
String errorMsg = "Verification of the hash for ledger metadata failed! --[HASH=" + key + "]"; | |||||
LOGGER.error(errorMsg); | |||||
throw new LedgerException(errorMsg); | |||||
} | |||||
return deserializeMetadata(bytes); | |||||
} | |||||
private Bytes encodeSettingsKey(HashDigest settingsHash) { | |||||
return settingPrefix.concat(settingsHash); | |||||
} | |||||
private Bytes encodeMetadataKey(HashDigest metadataHash) { | |||||
// return LEDGER_META_PREFIX + metadataHash; | |||||
// return metaPrefix + metadataHash; | |||||
return metaPrefix.concat(metadataHash); | |||||
} | |||||
/* | |||||
* (non-Javadoc) | |||||
* | |||||
* @see com.jd.blockchain.ledger.core.LedgerAdministration#getMetadata() | |||||
*/ | |||||
@Override | |||||
public LedgerMetadata_V2 getMetadata() { | |||||
return metadata; | |||||
} | |||||
// /** | |||||
// * 返回原来的账本配置; | |||||
// * | |||||
// * <br> | |||||
// * 此方法总是返回从上一个区块加载的账本配置,即时调用 {@link #setLedgerSetting(LedgerSettings)} 做出了新的更改; | |||||
// * | |||||
// * @return | |||||
// */ | |||||
// public LedgerSettings getPreviousSetting() { | |||||
// return previousSettings; | |||||
// } | |||||
/** | |||||
* 返回当前设置的账本配置; | |||||
* | |||||
* @return | |||||
*/ | |||||
public LedgerSettings getSettings() { | |||||
return settings; | |||||
} | |||||
/** | |||||
* 更新账本配置; | |||||
* | |||||
* @param ledgerSetting | |||||
*/ | |||||
public void setLedgerSetting(LedgerSettings ledgerSetting) { | |||||
if (readonly) { | |||||
throw new IllegalArgumentException("This merkle dataset is readonly!"); | |||||
} | |||||
settings = ledgerSetting; | |||||
updated = true; | |||||
} | |||||
@Override | |||||
public long getParticipantCount() { | |||||
return participants.getParticipantCount(); | |||||
} | |||||
@Override | |||||
public ParticipantNode[] getParticipants() { | |||||
return participants.getParticipants(); | |||||
} | |||||
@Override | |||||
public ParticipantDataset getParticipantDataset() { | |||||
return participants; | |||||
} | |||||
/** | |||||
* 加入新的参与方; 如果指定的参与方已经存在,则引发 LedgerException 异常; | |||||
* | |||||
* @param participant | |||||
*/ | |||||
public void addParticipant(ParticipantNode participant) { | |||||
participants.addConsensusParticipant(participant); | |||||
} | |||||
@Override | |||||
public boolean isUpdated() { | |||||
return updated || participants.isUpdated() || rolePrivileges.isUpdated() || userRoles.isUpdated(); | |||||
} | |||||
@Override | |||||
public void commit() { | |||||
if (!isUpdated()) { | |||||
return; | |||||
} | |||||
// 计算并更新参与方集合的根哈希; | |||||
participants.commit(); | |||||
metadata.setParticipantsHash(participants.getRootHash()); | |||||
// 计算并更新角色权限集合的根哈希; | |||||
rolePrivileges.commit(); | |||||
metadata.setRolePrivilegesHash(rolePrivileges.getRootHash()); | |||||
// 计算并更新用户角色授权集合的根哈希; | |||||
userRoles.commit(); | |||||
metadata.setUserRolesHash(userRoles.getRootHash()); | |||||
// 当前区块上下文的密码参数设置的哈希函数; | |||||
HashFunction hashFunc = Crypto.getHashFunction(previousSettings.getCryptoSetting().getHashAlgorithm()); | |||||
// 计算并更新参数配置的哈希; | |||||
if (settings == null) { | |||||
throw new LedgerException("Missing ledger settings!"); | |||||
} | |||||
byte[] settingsBytes = serializeSetting(settings); | |||||
HashDigest settingsHash = hashFunc.hash(settingsBytes); | |||||
metadata.setSettingsHash(settingsHash); | |||||
if (previousSettingHash == null || !previousSettingHash.equals(settingsHash)) { | |||||
Bytes settingsKey = encodeSettingsKey(settingsHash); | |||||
boolean nx = storage.set(settingsKey, settingsBytes, ExPolicy.NOT_EXISTING); | |||||
if (!nx) { | |||||
String base58MetadataHash = settingsHash.toBase58(); | |||||
// 有可能发生了并发写入冲突,不同的节点都向同一个存储服务器上写入数据; | |||||
String errMsg = "Ledger metadata already exist! --[MetadataHash=" + base58MetadataHash + "]"; | |||||
LOGGER.warn(errMsg); | |||||
throw new LedgerException(errMsg); | |||||
} | |||||
} | |||||
// 基于之前的密码配置来计算元数据的哈希; | |||||
byte[] metadataBytes = serializeMetadata(metadata); | |||||
HashDigest metadataHash = hashFunc.hash(metadataBytes); | |||||
if (adminDataHash == null || !adminDataHash.equals(metadataHash)) { | |||||
// update modify; | |||||
// String base58MetadataHash = metadataHash.toBase58(); | |||||
// String metadataKey = encodeMetadataKey(base58MetadataHash); | |||||
Bytes metadataKey = encodeMetadataKey(metadataHash); | |||||
boolean nx = storage.set(metadataKey, metadataBytes, ExPolicy.NOT_EXISTING); | |||||
if (!nx) { | |||||
String base58MetadataHash = metadataHash.toBase58(); | |||||
// 有可能发生了并发写入冲突,不同的节点都向同一个存储服务器上写入数据; | |||||
String errMsg = "Ledger metadata already exist! --[MetadataHash=" + base58MetadataHash + "]"; | |||||
LOGGER.warn(errMsg); | |||||
throw new LedgerException(errMsg); | |||||
} | |||||
adminDataHash = metadataHash; | |||||
} | |||||
updated = false; | |||||
} | |||||
private LedgerMetadata_V2 deserializeMetadata(byte[] bytes) { | |||||
return BinaryProtocol.decode(bytes); | |||||
} | |||||
private byte[] serializeMetadata(LedgerMetadataInfo config) { | |||||
return BinaryProtocol.encode(config, LedgerMetadata_V2.class); | |||||
} | |||||
@Override | |||||
public void cancel() { | |||||
if (!isUpdated()) { | |||||
return; | |||||
} | |||||
participants.cancel(); | |||||
metadata =origMetadata == null ? new LedgerMetadataInfo() : new LedgerMetadataInfo(origMetadata); | |||||
} | |||||
public static class LedgerMetadataInfo implements LedgerMetadata_V2 { | |||||
private byte[] seed; | |||||
// private LedgerSetting setting; | |||||
private HashDigest participantsHash; | |||||
private HashDigest settingsHash; | |||||
private HashDigest rolePrivilegesHash; | |||||
private HashDigest userRolesHash; | |||||
public LedgerMetadataInfo() { | |||||
} | |||||
public LedgerMetadataInfo(LedgerMetadata_V2 metadata) { | |||||
this.seed = metadata.getSeed(); | |||||
this.participantsHash = metadata.getParticipantsHash(); | |||||
this.settingsHash = metadata.getSettingsHash(); | |||||
this.rolePrivilegesHash = metadata.getRolePrivilegesHash(); | |||||
this.userRolesHash = metadata.getUserRolesHash(); | |||||
} | |||||
@Override | |||||
public byte[] getSeed() { | |||||
return seed; | |||||
} | |||||
@Override | |||||
public HashDigest getSettingsHash() { | |||||
return settingsHash; | |||||
} | |||||
@Override | |||||
public HashDigest getParticipantsHash() { | |||||
return participantsHash; | |||||
} | |||||
@Override | |||||
public HashDigest getRolePrivilegesHash() { | |||||
return rolePrivilegesHash; | |||||
} | |||||
@Override | |||||
public HashDigest getUserRolesHash() { | |||||
return userRolesHash; | |||||
} | |||||
public void setSeed(byte[] seed) { | |||||
this.seed = seed; | |||||
} | |||||
public void setSettingsHash(HashDigest settingHash) { | |||||
this.settingsHash = settingHash; | |||||
} | |||||
public void setParticipantsHash(HashDigest participantsHash) { | |||||
this.participantsHash = participantsHash; | |||||
} | |||||
public void setRolePrivilegesHash(HashDigest rolePrivilegesHash) { | |||||
this.rolePrivilegesHash = rolePrivilegesHash; | |||||
} | |||||
public void setUserRolesHash(HashDigest userRolesHash) { | |||||
this.userRolesHash = userRolesHash; | |||||
} | |||||
} | |||||
} |
@@ -1,5 +0,0 @@ | |||||
package com.jd.blockchain.ledger.core; | |||||
public enum LedgerAdminPrivilege { | |||||
} |
@@ -1,16 +0,0 @@ | |||||
package com.jd.blockchain.ledger.core; | |||||
import com.jd.blockchain.ledger.LedgerMetadata; | |||||
import com.jd.blockchain.ledger.ParticipantNode; | |||||
public interface LedgerAdministration { | |||||
LedgerMetadata getMetadata(); | |||||
long getParticipantCount(); | |||||
// ParticipantNode getParticipant(int id); | |||||
ParticipantNode[] getParticipants(); | |||||
} |
@@ -1,4 +1,4 @@ | |||||
package com.jd.blockchain.ledger.core.impl; | |||||
package com.jd.blockchain.ledger.core; | |||||
import com.jd.blockchain.binaryproto.DataContractRegistry; | import com.jd.blockchain.binaryproto.DataContractRegistry; | ||||
import com.jd.blockchain.crypto.HashDigest; | import com.jd.blockchain.crypto.HashDigest; |
@@ -1,10 +1,10 @@ | |||||
package com.jd.blockchain.ledger.core; | package com.jd.blockchain.ledger.core; | ||||
import com.jd.blockchain.ledger.CryptoSetting; | import com.jd.blockchain.ledger.CryptoSetting; | ||||
import com.jd.blockchain.ledger.LedgerSetting; | |||||
import com.jd.blockchain.ledger.LedgerSettings; | |||||
import com.jd.blockchain.utils.Bytes; | import com.jd.blockchain.utils.Bytes; | ||||
public class LedgerConfiguration implements LedgerSetting { | |||||
public class LedgerConfiguration implements LedgerSettings { | |||||
private String consensusProvider; | private String consensusProvider; | ||||
@@ -16,7 +16,7 @@ public class LedgerConfiguration implements LedgerSetting { | |||||
this.cryptoSetting = new CryptoConfig(); | this.cryptoSetting = new CryptoConfig(); | ||||
} | } | ||||
public LedgerConfiguration(LedgerSetting origSetting) { | |||||
public LedgerConfiguration(LedgerSettings origSetting) { | |||||
if (origSetting != null) { | if (origSetting != null) { | ||||
this.consensusProvider = origSetting.getConsensusProvider(); | this.consensusProvider = origSetting.getConsensusProvider(); | ||||
this.consensusSetting = origSetting.getConsensusSetting(); | this.consensusSetting = origSetting.getConsensusSetting(); | ||||
@@ -0,0 +1,19 @@ | |||||
package com.jd.blockchain.ledger.core; | |||||
/** | |||||
* {@link LedgerDataset} 表示账本在某一个区块上的数据集合; | |||||
* | |||||
* @author huanghaiquan | |||||
* | |||||
*/ | |||||
public interface LedgerDataQuery{ | |||||
LedgerAdminDataQuery getAdminDataset(); | |||||
UserAccountQuery getUserAccountSet(); | |||||
DataAccountQuery getDataAccountSet(); | |||||
ContractAccountQuery getContractAccountset(); | |||||
} |
@@ -1,21 +0,0 @@ | |||||
package com.jd.blockchain.ledger.core; | |||||
/** | |||||
* {@link LedgerDataSet} 表示账本在某一个区块上的数据集合; | |||||
* | |||||
* @author huanghaiquan | |||||
* | |||||
*/ | |||||
public interface LedgerDataSet{ | |||||
boolean isReadonly(); | |||||
LedgerAdminAccount getAdminAccount(); | |||||
UserAccountSet getUserAccountSet(); | |||||
DataAccountSet getDataAccountSet(); | |||||
ContractAccountSet getContractAccountSet(); | |||||
} |
@@ -1,33 +1,31 @@ | |||||
package com.jd.blockchain.ledger.core.impl; | |||||
package com.jd.blockchain.ledger.core; | |||||
import com.jd.blockchain.ledger.core.*; | |||||
import com.jd.blockchain.utils.Transactional; | import com.jd.blockchain.utils.Transactional; | ||||
public class LedgerDataSetImpl implements LedgerDataSet, Transactional { | |||||
public class LedgerDataset implements LedgerDataQuery, Transactional { | |||||
private LedgerAdminAccount adminAccount; | |||||
private LedgerAdminDataset adminDataset; | |||||
private UserAccountSet userAccountSet; | private UserAccountSet userAccountSet; | ||||
private DataAccountSet dataAccountSet; | private DataAccountSet dataAccountSet; | ||||
private ContractAccountSet contractAccountSet; | private ContractAccountSet contractAccountSet; | ||||
private boolean readonly; | |||||
private boolean readonly; | |||||
/** | /** | ||||
* Create new block; | * Create new block; | ||||
* | |||||
* @param adminAccount | * @param adminAccount | ||||
* @param userAccountSet | * @param userAccountSet | ||||
* @param dataAccountSet | * @param dataAccountSet | ||||
* @param contractAccountSet | * @param contractAccountSet | ||||
* @param readonly | * @param readonly | ||||
*/ | */ | ||||
public LedgerDataSetImpl(LedgerAdminAccount adminAccount, | |||||
UserAccountSet userAccountSet, DataAccountSet dataAccountSet, ContractAccountSet contractAccountSet, | |||||
boolean readonly) { | |||||
this.adminAccount = adminAccount; | |||||
public LedgerDataset(LedgerAdminDataset adminAccount, UserAccountSet userAccountSet, | |||||
DataAccountSet dataAccountSet, ContractAccountSet contractAccountSet, boolean readonly) { | |||||
this.adminDataset = adminAccount; | |||||
this.userAccountSet = userAccountSet; | this.userAccountSet = userAccountSet; | ||||
this.dataAccountSet = dataAccountSet; | this.dataAccountSet = dataAccountSet; | ||||
this.contractAccountSet = contractAccountSet; | this.contractAccountSet = contractAccountSet; | ||||
@@ -36,8 +34,8 @@ public class LedgerDataSetImpl implements LedgerDataSet, Transactional { | |||||
} | } | ||||
@Override | @Override | ||||
public LedgerAdminAccount getAdminAccount() { | |||||
return adminAccount; | |||||
public LedgerAdminDataset getAdminDataset() { | |||||
return adminDataset; | |||||
} | } | ||||
@Override | @Override | ||||
@@ -51,13 +49,13 @@ public class LedgerDataSetImpl implements LedgerDataSet, Transactional { | |||||
} | } | ||||
@Override | @Override | ||||
public ContractAccountSet getContractAccountSet() { | |||||
public ContractAccountSet getContractAccountset() { | |||||
return contractAccountSet; | return contractAccountSet; | ||||
} | } | ||||
@Override | @Override | ||||
public boolean isUpdated() { | public boolean isUpdated() { | ||||
return adminAccount.isUpdated() || userAccountSet.isUpdated() || dataAccountSet.isUpdated() | |||||
return adminDataset.isUpdated() || userAccountSet.isUpdated() || dataAccountSet.isUpdated() | |||||
|| contractAccountSet.isUpdated(); | || contractAccountSet.isUpdated(); | ||||
} | } | ||||
@@ -70,7 +68,7 @@ public class LedgerDataSetImpl implements LedgerDataSet, Transactional { | |||||
return; | return; | ||||
} | } | ||||
adminAccount.commit(); | |||||
adminDataset.commit(); | |||||
userAccountSet.commit(); | userAccountSet.commit(); | ||||
dataAccountSet.commit(); | dataAccountSet.commit(); | ||||
contractAccountSet.commit(); | contractAccountSet.commit(); | ||||
@@ -78,15 +76,22 @@ public class LedgerDataSetImpl implements LedgerDataSet, Transactional { | |||||
@Override | @Override | ||||
public void cancel() { | public void cancel() { | ||||
adminAccount.cancel(); | |||||
adminDataset.cancel(); | |||||
userAccountSet.cancel(); | userAccountSet.cancel(); | ||||
dataAccountSet.cancel(); | dataAccountSet.cancel(); | ||||
contractAccountSet.cancel(); | contractAccountSet.cancel(); | ||||
} | } | ||||
@Override | |||||
public boolean isReadonly() { | public boolean isReadonly() { | ||||
return readonly; | return readonly; | ||||
} | } | ||||
void setReadonly() { | |||||
this.readonly = true; | |||||
this.adminDataset.setReadonly(); | |||||
this.userAccountSet.setReadonly(); | |||||
this.dataAccountSet.setReadonly(); | |||||
this.contractAccountSet.setReadonly(); | |||||
} | |||||
} | } |
@@ -11,7 +11,7 @@ import com.jd.blockchain.ledger.TransactionRequest; | |||||
* <p> | * <p> | ||||
* | * | ||||
* {@link LedgerEditor} 以上一个区块作为数据编辑的起点; <br> | * {@link LedgerEditor} 以上一个区块作为数据编辑的起点; <br> | ||||
* 对账本数据({@link #getDataSet()})的批量更改可以作为一个交易({@link LedgerTransaction})整体提交暂存,形成暂存点; | |||||
* 对账本数据({@link #getDataset()})的批量更改可以作为一个交易({@link LedgerTransaction})整体提交暂存,形成暂存点; | |||||
* <br> | * <br> | ||||
* | * | ||||
* @author huanghaiquan | * @author huanghaiquan | ||||
@@ -33,11 +33,25 @@ public interface LedgerEditor { | |||||
*/ | */ | ||||
long getBlockHeight(); | long getBlockHeight(); | ||||
/** | |||||
* 最新的账本数据集; | |||||
* | |||||
* @return | |||||
*/ | |||||
LedgerDataset getLedgerDataset(); | |||||
/** | |||||
* 最新的交易集合; | |||||
* | |||||
* @return | |||||
*/ | |||||
TransactionSet getTransactionSet(); | |||||
/** | /** | ||||
* 开始新事务;<br> | * 开始新事务;<br> | ||||
* | * | ||||
* 方法返回之前,将会校验交易请求的用户签名列表和节点签名列表,并在后续对数据集 | * 方法返回之前,将会校验交易请求的用户签名列表和节点签名列表,并在后续对数据集 | ||||
* {@link LedgerTransactionContext#getDataSet()} 的操作时,校验这些用户和节点是否具备权限;<br> | |||||
* {@link LedgerTransactionContext#getDataset()} 的操作时,校验这些用户和节点是否具备权限;<br> | |||||
* | * | ||||
* 校验失败将引发异常 {@link LedgerException}; | * 校验失败将引发异常 {@link LedgerException}; | ||||
* <p> | * <p> | ||||
@@ -52,7 +66,8 @@ public interface LedgerEditor { | |||||
* | * | ||||
* | * | ||||
* | * | ||||
* 注:方法不解析、不执行交易中的操作;<p> | |||||
* 注:方法不解析、不执行交易中的操作; | |||||
* <p> | |||||
* | * | ||||
* @param txRequest 交易请求; | * @param txRequest 交易请求; | ||||
* @return | * @return | ||||
@@ -13,8 +13,8 @@ import com.jd.blockchain.ledger.LedgerInitOperation; | |||||
* @author huanghaiquan | * @author huanghaiquan | ||||
* | * | ||||
*/ | */ | ||||
@DataContract(code = DataCodes.METADATA_INIT_PERMISSION) | |||||
public interface LedgerInitPermission { | |||||
@DataContract(code = DataCodes.METADATA_INIT_PROPOSAL) | |||||
public interface LedgerInitProposal { | |||||
/** | /** | ||||
* 做出许可的参与方 ID; | * 做出许可的参与方 ID; |
@@ -2,7 +2,7 @@ package com.jd.blockchain.ledger.core; | |||||
import com.jd.blockchain.crypto.SignatureDigest; | import com.jd.blockchain.crypto.SignatureDigest; | ||||
public class LedgerInitPermissionData implements LedgerInitPermission { | |||||
public class LedgerInitProposalData implements LedgerInitProposal { | |||||
private int participantId; | private int participantId; | ||||
@@ -11,10 +11,11 @@ public class LedgerInitPermissionData implements LedgerInitPermission { | |||||
/** | /** | ||||
* a private contructor for deserialize; | * a private contructor for deserialize; | ||||
*/ | */ | ||||
private LedgerInitPermissionData() { | |||||
@SuppressWarnings("unused") | |||||
private LedgerInitProposalData() { | |||||
} | } | ||||
public LedgerInitPermissionData(int participantId, SignatureDigest initTxSignature) { | |||||
public LedgerInitProposalData(int participantId, SignatureDigest initTxSignature) { | |||||
this.participantId = participantId; | this.participantId = participantId; | ||||
this.transactionSignature = initTxSignature; | this.transactionSignature = initTxSignature; | ||||
} | } |
@@ -0,0 +1,215 @@ | |||||
package com.jd.blockchain.ledger.core; | |||||
import com.jd.blockchain.crypto.HashDigest; | |||||
import com.jd.blockchain.crypto.PrivKey; | |||||
import com.jd.blockchain.crypto.SignatureDigest; | |||||
import com.jd.blockchain.ledger.BlockchainIdentity; | |||||
import com.jd.blockchain.ledger.BlockchainIdentityData; | |||||
import com.jd.blockchain.ledger.DigitalSignature; | |||||
import com.jd.blockchain.ledger.LedgerBlock; | |||||
import com.jd.blockchain.ledger.LedgerInitException; | |||||
import com.jd.blockchain.ledger.LedgerInitOperation; | |||||
import com.jd.blockchain.ledger.LedgerInitSetting; | |||||
import com.jd.blockchain.ledger.ParticipantNode; | |||||
import com.jd.blockchain.ledger.RoleInitSettings; | |||||
import com.jd.blockchain.ledger.RolesConfigureOperation; | |||||
import com.jd.blockchain.ledger.SecurityInitSettings; | |||||
import com.jd.blockchain.ledger.TransactionBuilder; | |||||
import com.jd.blockchain.ledger.TransactionContent; | |||||
import com.jd.blockchain.ledger.TransactionRequest; | |||||
import com.jd.blockchain.ledger.UserAuthInitSettings; | |||||
import com.jd.blockchain.ledger.UserAuthorizeOperation; | |||||
import com.jd.blockchain.ledger.UserRegisterOperation; | |||||
import com.jd.blockchain.service.TransactionBatchResultHandle; | |||||
import com.jd.blockchain.storage.service.KVStorageService; | |||||
import com.jd.blockchain.transaction.SignatureUtils; | |||||
import com.jd.blockchain.transaction.TxBuilder; | |||||
import com.jd.blockchain.transaction.TxRequestBuilder; | |||||
public class LedgerInitializer { | |||||
private static final FullPermissionedSecurityManager FULL_PERMISSION_SECURITY_MANAGER = new FullPermissionedSecurityManager(); | |||||
private static final LedgerDataQuery EMPTY_LEDGER_DATA_QUERY = new EmptyLedgerDataset(); | |||||
private static final OperationHandleRegisteration DEFAULT_OP_HANDLE_REG = new DefaultOperationHandleRegisteration(); | |||||
private LedgerService EMPTY_LEDGERS = new LedgerManager(); | |||||
private LedgerInitSetting initSetting; | |||||
private TransactionContent initTxContent; | |||||
private volatile LedgerBlock genesisBlock; | |||||
private volatile LedgerEditor ledgerEditor; | |||||
private volatile boolean committed = false; | |||||
private volatile boolean canceled = false; | |||||
private TransactionBatchResultHandle txResultsHandle; | |||||
/** | |||||
* 初始化生成的账本hash; <br> | |||||
* | |||||
* 在成功执行 {@link #prepareLedger(KVStorageService, DigitalSignature...)} 之前总是返回 | |||||
* null; | |||||
* | |||||
* @return | |||||
*/ | |||||
public HashDigest getLedgerHash() { | |||||
return genesisBlock == null ? null : genesisBlock.getHash(); | |||||
} | |||||
/** | |||||
* @param initSetting | |||||
* @param initTxContent | |||||
*/ | |||||
private LedgerInitializer(LedgerInitSetting initSetting, TransactionContent initTxContent) { | |||||
this.initSetting = initSetting; | |||||
this.initTxContent = initTxContent; | |||||
} | |||||
public TransactionContent getTransactionContent() { | |||||
return initTxContent; | |||||
} | |||||
private static SecurityInitSettings createDefaultSecurityInitSettings() { | |||||
// TODO throw new IllegalStateException("Not implemented!"); | |||||
return null; | |||||
} | |||||
// public static LedgerInitializer create(LedgerInitSetting initSetting) { | |||||
// return create(initSetting, createDefaultSecurityInitSettings()); | |||||
// } | |||||
public static LedgerInitializer create(LedgerInitSetting initSetting, SecurityInitSettings securityInitSettings) { | |||||
// 生成创世交易; | |||||
TransactionContent initTxContent = buildGenesisTransaction(initSetting, securityInitSettings); | |||||
return new LedgerInitializer(initSetting, initTxContent); | |||||
} | |||||
/** | |||||
* 根据初始化配置,生成创始交易; | |||||
* <p> | |||||
* | |||||
* “创世交易”按顺序由以下操作组成:<br> | |||||
* (1) 账本初始化 {@link LedgerInitOperation}:此操作仅用于锚定了原始的交易配置,对应的 | |||||
* {@link OperationHandle} 执行空操作,由“创世交易”其余的操作来表达对账本的实际修改;<br> | |||||
* (2) 注册用户 {@link UserRegisterOperation}:有一项或者多项;<br> | |||||
* (3) 配置角色 {@link RolesConfigureOperation}:有一项或者多项;<br> | |||||
* (4) 授权用户 {@link UserAuthorizeOperation}:有一项或者多项;<br> | |||||
* | |||||
* @param initSetting | |||||
* @param securityInitSettings | |||||
* @return | |||||
*/ | |||||
public static TransactionContent buildGenesisTransaction(LedgerInitSetting initSetting, | |||||
SecurityInitSettings securityInitSettings) { | |||||
// 账本初始化交易的账本 hash 为 null; | |||||
TransactionBuilder initTxBuilder = new TxBuilder(null); | |||||
// 定义账本初始化操作; | |||||
initTxBuilder.ledgers().create(initSetting); | |||||
// TODO: 注册参与方; 目前由 LedgerInitSetting 定义,在 LedgerAdminDataset 中解释执行; | |||||
// 注册用户; | |||||
for (ParticipantNode p : initSetting.getConsensusParticipants()) { | |||||
// TODO:暂时只支持注册用户的初始化操作; | |||||
BlockchainIdentity superUserId = new BlockchainIdentityData(p.getPubKey()); | |||||
initTxBuilder.users().register(superUserId); | |||||
} | |||||
// 配置角色; | |||||
for (RoleInitSettings roleSettings : securityInitSettings.getRoles()) { | |||||
initTxBuilder.security().roles().configure(roleSettings.getRoleName()) | |||||
.enable(roleSettings.getLedgerPermissions()).enable(roleSettings.getTransactionPermissions()); | |||||
} | |||||
// 授权用户; | |||||
for (UserAuthInitSettings userAuthSettings : securityInitSettings.getUserAuthorizations()) { | |||||
initTxBuilder.security().authorziations().forUser(userAuthSettings.getUserAddress()) | |||||
.authorize(userAuthSettings.getRoles()) | |||||
.setPolicy(userAuthSettings.getPolicy()); | |||||
} | |||||
// 账本初始化配置声明的创建时间来初始化交易时间戳;注:不能用本地时间,因为共识节点之间的本地时间系统不一致; | |||||
return initTxBuilder.prepareContent(initSetting.getCreatedTime()); | |||||
} | |||||
public SignatureDigest signTransaction(PrivKey privKey) { | |||||
return SignatureUtils.sign(initTxContent, privKey); | |||||
} | |||||
/** | |||||
* 准备创建账本; | |||||
* | |||||
* @param storageService 存储服务; | |||||
* @param nodeSignatures 节点签名列表; | |||||
* @return | |||||
*/ | |||||
public LedgerBlock prepareLedger(KVStorageService storageService, DigitalSignature... nodeSignatures) { | |||||
if (genesisBlock != null) { | |||||
throw new LedgerInitException("The ledger has been prepared!"); | |||||
} | |||||
// 生成账本; | |||||
this.ledgerEditor = createLedgerEditor(this.initSetting, storageService); | |||||
this.genesisBlock = prepareLedger(ledgerEditor, nodeSignatures); | |||||
return genesisBlock; | |||||
} | |||||
public void commit() { | |||||
if (committed) { | |||||
throw new LedgerInitException("The ledger has been committed!"); | |||||
} | |||||
if (canceled) { | |||||
throw new LedgerInitException("The ledger has been canceled!"); | |||||
} | |||||
committed = true; | |||||
this.txResultsHandle.commit(); | |||||
} | |||||
public void cancel() { | |||||
if (canceled) { | |||||
throw new LedgerInitException("The ledger has been canceled!"); | |||||
} | |||||
if (committed) { | |||||
throw new LedgerInitException("The ledger has been committed!"); | |||||
} | |||||
this.ledgerEditor.cancel(); | |||||
} | |||||
public static LedgerEditor createLedgerEditor(LedgerInitSetting initSetting, KVStorageService storageService) { | |||||
LedgerEditor genesisBlockEditor = LedgerTransactionalEditor.createEditor(initSetting, | |||||
LedgerManage.LEDGER_PREFIX, storageService.getExPolicyKVStorage(), | |||||
storageService.getVersioningKVStorage()); | |||||
return genesisBlockEditor; | |||||
} | |||||
/** | |||||
* 初始化账本数据,返回创始区块; | |||||
* | |||||
* @param ledgerEditor | |||||
* @return | |||||
*/ | |||||
private LedgerBlock prepareLedger(LedgerEditor ledgerEditor, DigitalSignature... nodeSignatures) { | |||||
// 初始化时,自动将参与方注册为账本的用户; | |||||
TxRequestBuilder txReqBuilder = new TxRequestBuilder(this.initTxContent); | |||||
txReqBuilder.addNodeSignature(nodeSignatures); | |||||
TransactionRequest txRequest = txReqBuilder.buildRequest(); | |||||
TransactionBatchProcessor txProcessor = new TransactionBatchProcessor(FULL_PERMISSION_SECURITY_MANAGER, | |||||
ledgerEditor, EMPTY_LEDGER_DATA_QUERY, DEFAULT_OP_HANDLE_REG, EMPTY_LEDGERS); | |||||
txProcessor.schedule(txRequest); | |||||
txResultsHandle = txProcessor.prepare(); | |||||
return txResultsHandle.getBlock(); | |||||
} | |||||
} |
@@ -12,19 +12,21 @@ import com.jd.blockchain.storage.service.KVStorageService; | |||||
*/ | */ | ||||
public interface LedgerManage extends LedgerService { | public interface LedgerManage extends LedgerService { | ||||
static final String LEDGER_PREFIX = "LDG://"; | |||||
LedgerRepository register(HashDigest ledgerHash, KVStorageService storageService); | LedgerRepository register(HashDigest ledgerHash, KVStorageService storageService); | ||||
void unregister(HashDigest ledgerHash); | void unregister(HashDigest ledgerHash); | ||||
/** | |||||
* 创建新账本; | |||||
* | |||||
* @param initSetting | |||||
* 初始化配置; | |||||
* @param initPermissions | |||||
* 参与者的初始化授权列表;与参与者列表一致; | |||||
* @return | |||||
*/ | |||||
LedgerEditor newLedger(LedgerInitSetting initSetting, KVStorageService storageService); | |||||
// /** | |||||
// * 创建新账本; | |||||
// * | |||||
// * @param initSetting | |||||
// * 初始化配置; | |||||
// * @param initPermissions | |||||
// * 参与者的初始化授权列表;与参与者列表一致; | |||||
// * @return | |||||
// */ | |||||
// LedgerEditor newLedger(LedgerInitSetting initSetting, KVStorageService storageService); | |||||
} | } |
@@ -1,4 +1,4 @@ | |||||
package com.jd.blockchain.ledger.core.impl; | |||||
package com.jd.blockchain.ledger.core; | |||||
import java.util.HashMap; | import java.util.HashMap; | ||||
import java.util.Map; | import java.util.Map; | ||||
@@ -9,11 +9,6 @@ import com.jd.blockchain.crypto.CryptoProvider; | |||||
import com.jd.blockchain.crypto.HashDigest; | import com.jd.blockchain.crypto.HashDigest; | ||||
import com.jd.blockchain.ledger.CryptoSetting; | import com.jd.blockchain.ledger.CryptoSetting; | ||||
import com.jd.blockchain.ledger.LedgerException; | import com.jd.blockchain.ledger.LedgerException; | ||||
import com.jd.blockchain.ledger.LedgerInitSetting; | |||||
import com.jd.blockchain.ledger.core.LedgerConsts; | |||||
import com.jd.blockchain.ledger.core.LedgerEditor; | |||||
import com.jd.blockchain.ledger.core.LedgerManage; | |||||
import com.jd.blockchain.ledger.core.LedgerRepository; | |||||
import com.jd.blockchain.storage.service.ExPolicyKVStorage; | import com.jd.blockchain.storage.service.ExPolicyKVStorage; | ||||
import com.jd.blockchain.storage.service.KVStorageService; | import com.jd.blockchain.storage.service.KVStorageService; | ||||
import com.jd.blockchain.storage.service.VersioningKVStorage; | import com.jd.blockchain.storage.service.VersioningKVStorage; | ||||
@@ -27,8 +22,6 @@ import com.jd.blockchain.utils.codec.Base58Utils; | |||||
*/ | */ | ||||
public class LedgerManager implements LedgerManage { | public class LedgerManager implements LedgerManage { | ||||
private static final String LEDGER_PREFIX = "LDG://"; | |||||
// @Autowired | // @Autowired | ||||
// private ExistentialKVStorage exPolicyStorage; | // private ExistentialKVStorage exPolicyStorage; | ||||
// | // | ||||
@@ -69,7 +62,7 @@ public class LedgerManager implements LedgerManage { | |||||
ledgerVersioningStorage); | ledgerVersioningStorage); | ||||
// 校验 crypto service provider ; | // 校验 crypto service provider ; | ||||
CryptoSetting cryptoSetting = ledgerRepo.getAdminAccount().getSetting().getCryptoSetting(); | |||||
CryptoSetting cryptoSetting = ledgerRepo.getAdminInfo().getSettings().getCryptoSetting(); | |||||
checkCryptoSetting(cryptoSetting, ledgerHash); | checkCryptoSetting(cryptoSetting, ledgerHash); | ||||
// 创建账本上下文; | // 创建账本上下文; | ||||
@@ -142,18 +135,18 @@ public class LedgerManager implements LedgerManage { | |||||
} | } | ||||
} | } | ||||
/* | |||||
* (non-Javadoc) | |||||
* | |||||
* @see com.jd.blockchain.ledger.core.LedgerManager#newLedger(com.jd.blockchain. | |||||
* ledger.core.ConsensusConfig, com.jd.blockchain.ledger.core.CryptoConfig) | |||||
*/ | |||||
@Override | |||||
public LedgerEditor newLedger(LedgerInitSetting initSetting, KVStorageService storageService) { | |||||
LedgerEditor genesisBlockEditor = LedgerTransactionalEditor.createEditor(initSetting, LEDGER_PREFIX, | |||||
storageService.getExPolicyKVStorage(), storageService.getVersioningKVStorage()); | |||||
return genesisBlockEditor; | |||||
} | |||||
// /* | |||||
// * (non-Javadoc) | |||||
// * | |||||
// * @see com.jd.blockchain.ledger.core.LedgerManager#newLedger(com.jd.blockchain. | |||||
// * ledger.core.ConsensusConfig, com.jd.blockchain.ledger.core.CryptoConfig) | |||||
// */ | |||||
// @Override | |||||
// public LedgerEditor newLedger(LedgerInitSetting initSetting, KVStorageService storageService) { | |||||
// LedgerEditor genesisBlockEditor = LedgerTransactionalEditor.createEditor(initSetting, LEDGER_PREFIX, | |||||
// storageService.getExPolicyKVStorage(), storageService.getVersioningKVStorage()); | |||||
// return genesisBlockEditor; | |||||
// } | |||||
static String getLedgerStoragePrefix(HashDigest ledgerHash) { | static String getLedgerStoragePrefix(HashDigest ledgerHash) { | ||||
String base58LedgerHash = Base58Utils.encode(ledgerHash.toBytes()); | String base58LedgerHash = Base58Utils.encode(ledgerHash.toBytes()); |
@@ -1,19 +1,25 @@ | |||||
package com.jd.blockchain.ledger.core.impl; | |||||
package com.jd.blockchain.ledger.core; | |||||
import java.util.ArrayList; | import java.util.ArrayList; | ||||
import java.util.List; | import java.util.List; | ||||
import com.jd.blockchain.contract.ContractException; | import com.jd.blockchain.contract.ContractException; | ||||
import com.jd.blockchain.crypto.HashDigest; | import com.jd.blockchain.crypto.HashDigest; | ||||
import com.jd.blockchain.ledger.*; | |||||
import com.jd.blockchain.ledger.core.ContractAccountSet; | |||||
import com.jd.blockchain.ledger.core.DataAccount; | |||||
import com.jd.blockchain.ledger.core.DataAccountSet; | |||||
import com.jd.blockchain.ledger.core.LedgerAdministration; | |||||
import com.jd.blockchain.ledger.core.LedgerRepository; | |||||
import com.jd.blockchain.ledger.core.LedgerService; | |||||
import com.jd.blockchain.ledger.core.TransactionSet; | |||||
import com.jd.blockchain.ledger.core.UserAccountSet; | |||||
import com.jd.blockchain.ledger.AccountHeader; | |||||
import com.jd.blockchain.ledger.BytesValue; | |||||
import com.jd.blockchain.ledger.ContractInfo; | |||||
import com.jd.blockchain.ledger.KVDataEntry; | |||||
import com.jd.blockchain.ledger.KVDataObject; | |||||
import com.jd.blockchain.ledger.KVDataVO; | |||||
import com.jd.blockchain.ledger.KVInfoVO; | |||||
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.LedgerTransaction; | |||||
import com.jd.blockchain.ledger.ParticipantNode; | |||||
import com.jd.blockchain.ledger.TransactionState; | |||||
import com.jd.blockchain.ledger.UserInfo; | |||||
import com.jd.blockchain.transaction.BlockchainQueryService; | import com.jd.blockchain.transaction.BlockchainQueryService; | ||||
import com.jd.blockchain.utils.Bytes; | import com.jd.blockchain.utils.Bytes; | ||||
import com.jd.blockchain.utils.QueryUtil; | import com.jd.blockchain.utils.QueryUtil; | ||||
@@ -42,15 +48,23 @@ public class LedgerQueryService implements BlockchainQueryService { | |||||
ledgerInfo.setLatestBlockHeight(ledger.getLatestBlockHeight()); | ledgerInfo.setLatestBlockHeight(ledger.getLatestBlockHeight()); | ||||
return ledgerInfo; | return ledgerInfo; | ||||
} | } | ||||
@Override | |||||
public LedgerAdminInfo getLedgerAdminInfo(HashDigest ledgerHash) { | |||||
LedgerRepository ledger = ledgerService.getLedger(ledgerHash); | |||||
LedgerBlock block = ledger.getLatestBlock(); | |||||
LedgerAdminInfo administration = ledger.getAdminInfo(block); | |||||
return administration; | |||||
} | |||||
@Override | @Override | ||||
public ParticipantNode[] getConsensusParticipants(HashDigest ledgerHash) { | public ParticipantNode[] getConsensusParticipants(HashDigest ledgerHash) { | ||||
return ledgerAdministration(ledgerHash).getParticipants(); | |||||
return getLedgerAdminInfo(ledgerHash).getParticipants(); | |||||
} | } | ||||
@Override | @Override | ||||
public LedgerMetadata getLedgerMetadata(HashDigest ledgerHash) { | public LedgerMetadata getLedgerMetadata(HashDigest ledgerHash) { | ||||
return ledgerAdministration(ledgerHash).getMetadata(); | |||||
return getLedgerAdminInfo(ledgerHash).getMetadata(); | |||||
} | } | ||||
@Override | @Override | ||||
@@ -93,7 +107,7 @@ public class LedgerQueryService implements BlockchainQueryService { | |||||
public long getDataAccountCount(HashDigest ledgerHash, long height) { | public long getDataAccountCount(HashDigest ledgerHash, long height) { | ||||
LedgerRepository ledger = ledgerService.getLedger(ledgerHash); | LedgerRepository ledger = ledgerService.getLedger(ledgerHash); | ||||
LedgerBlock block = ledger.getBlock(height); | LedgerBlock block = ledger.getBlock(height); | ||||
DataAccountSet dataAccountSet = ledger.getDataAccountSet(block); | |||||
DataAccountQuery dataAccountSet = ledger.getDataAccountSet(block); | |||||
return dataAccountSet.getTotalCount(); | return dataAccountSet.getTotalCount(); | ||||
} | } | ||||
@@ -101,7 +115,7 @@ public class LedgerQueryService implements BlockchainQueryService { | |||||
public long getDataAccountCount(HashDigest ledgerHash, HashDigest blockHash) { | public long getDataAccountCount(HashDigest ledgerHash, HashDigest blockHash) { | ||||
LedgerRepository ledger = ledgerService.getLedger(ledgerHash); | LedgerRepository ledger = ledgerService.getLedger(ledgerHash); | ||||
LedgerBlock block = ledger.getBlock(blockHash); | LedgerBlock block = ledger.getBlock(blockHash); | ||||
DataAccountSet dataAccountSet = ledger.getDataAccountSet(block); | |||||
DataAccountQuery dataAccountSet = ledger.getDataAccountSet(block); | |||||
return dataAccountSet.getTotalCount(); | return dataAccountSet.getTotalCount(); | ||||
} | } | ||||
@@ -109,7 +123,7 @@ public class LedgerQueryService implements BlockchainQueryService { | |||||
public long getDataAccountTotalCount(HashDigest ledgerHash) { | public long getDataAccountTotalCount(HashDigest ledgerHash) { | ||||
LedgerRepository ledger = ledgerService.getLedger(ledgerHash); | LedgerRepository ledger = ledgerService.getLedger(ledgerHash); | ||||
LedgerBlock block = ledger.getLatestBlock(); | LedgerBlock block = ledger.getLatestBlock(); | ||||
DataAccountSet dataAccountSet = ledger.getDataAccountSet(block); | |||||
DataAccountQuery dataAccountSet = ledger.getDataAccountSet(block); | |||||
return dataAccountSet.getTotalCount(); | return dataAccountSet.getTotalCount(); | ||||
} | } | ||||
@@ -117,7 +131,7 @@ public class LedgerQueryService implements BlockchainQueryService { | |||||
public long getUserCount(HashDigest ledgerHash, long height) { | public long getUserCount(HashDigest ledgerHash, long height) { | ||||
LedgerRepository ledger = ledgerService.getLedger(ledgerHash); | LedgerRepository ledger = ledgerService.getLedger(ledgerHash); | ||||
LedgerBlock block = ledger.getBlock(height); | LedgerBlock block = ledger.getBlock(height); | ||||
UserAccountSet userAccountSet = ledger.getUserAccountSet(block); | |||||
UserAccountQuery userAccountSet = ledger.getUserAccountSet(block); | |||||
return userAccountSet.getTotalCount(); | return userAccountSet.getTotalCount(); | ||||
} | } | ||||
@@ -125,7 +139,7 @@ public class LedgerQueryService implements BlockchainQueryService { | |||||
public long getUserCount(HashDigest ledgerHash, HashDigest blockHash) { | public long getUserCount(HashDigest ledgerHash, HashDigest blockHash) { | ||||
LedgerRepository ledger = ledgerService.getLedger(ledgerHash); | LedgerRepository ledger = ledgerService.getLedger(ledgerHash); | ||||
LedgerBlock block = ledger.getBlock(blockHash); | LedgerBlock block = ledger.getBlock(blockHash); | ||||
UserAccountSet userAccountSet = ledger.getUserAccountSet(block); | |||||
UserAccountQuery userAccountSet = ledger.getUserAccountSet(block); | |||||
return userAccountSet.getTotalCount(); | return userAccountSet.getTotalCount(); | ||||
} | } | ||||
@@ -133,7 +147,7 @@ public class LedgerQueryService implements BlockchainQueryService { | |||||
public long getUserTotalCount(HashDigest ledgerHash) { | public long getUserTotalCount(HashDigest ledgerHash) { | ||||
LedgerRepository ledger = ledgerService.getLedger(ledgerHash); | LedgerRepository ledger = ledgerService.getLedger(ledgerHash); | ||||
LedgerBlock block = ledger.getLatestBlock(); | LedgerBlock block = ledger.getLatestBlock(); | ||||
UserAccountSet userAccountSet = ledger.getUserAccountSet(block); | |||||
UserAccountQuery userAccountSet = ledger.getUserAccountSet(block); | |||||
return userAccountSet.getTotalCount(); | return userAccountSet.getTotalCount(); | ||||
} | } | ||||
@@ -141,7 +155,7 @@ public class LedgerQueryService implements BlockchainQueryService { | |||||
public long getContractCount(HashDigest ledgerHash, long height) { | public long getContractCount(HashDigest ledgerHash, long height) { | ||||
LedgerRepository ledger = ledgerService.getLedger(ledgerHash); | LedgerRepository ledger = ledgerService.getLedger(ledgerHash); | ||||
LedgerBlock block = ledger.getBlock(height); | LedgerBlock block = ledger.getBlock(height); | ||||
ContractAccountSet contractAccountSet = ledger.getContractAccountSet(block); | |||||
ContractAccountQuery contractAccountSet = ledger.getContractAccountSet(block); | |||||
return contractAccountSet.getTotalCount(); | return contractAccountSet.getTotalCount(); | ||||
} | } | ||||
@@ -149,7 +163,7 @@ public class LedgerQueryService implements BlockchainQueryService { | |||||
public long getContractCount(HashDigest ledgerHash, HashDigest blockHash) { | public long getContractCount(HashDigest ledgerHash, HashDigest blockHash) { | ||||
LedgerRepository ledger = ledgerService.getLedger(ledgerHash); | LedgerRepository ledger = ledgerService.getLedger(ledgerHash); | ||||
LedgerBlock block = ledger.getBlock(blockHash); | LedgerBlock block = ledger.getBlock(blockHash); | ||||
ContractAccountSet contractAccountSet = ledger.getContractAccountSet(block); | |||||
ContractAccountQuery contractAccountSet = ledger.getContractAccountSet(block); | |||||
return contractAccountSet.getTotalCount(); | return contractAccountSet.getTotalCount(); | ||||
} | } | ||||
@@ -157,7 +171,7 @@ public class LedgerQueryService implements BlockchainQueryService { | |||||
public long getContractTotalCount(HashDigest ledgerHash) { | public long getContractTotalCount(HashDigest ledgerHash) { | ||||
LedgerRepository ledger = ledgerService.getLedger(ledgerHash); | LedgerRepository ledger = ledgerService.getLedger(ledgerHash); | ||||
LedgerBlock block = ledger.getLatestBlock(); | LedgerBlock block = ledger.getLatestBlock(); | ||||
ContractAccountSet contractAccountSet = ledger.getContractAccountSet(block); | |||||
ContractAccountQuery contractAccountSet = ledger.getContractAccountSet(block); | |||||
return contractAccountSet.getTotalCount(); | return contractAccountSet.getTotalCount(); | ||||
} | } | ||||
@@ -240,7 +254,7 @@ public class LedgerQueryService implements BlockchainQueryService { | |||||
public UserInfo getUser(HashDigest ledgerHash, String address) { | public UserInfo getUser(HashDigest ledgerHash, String address) { | ||||
LedgerRepository ledger = ledgerService.getLedger(ledgerHash); | LedgerRepository ledger = ledgerService.getLedger(ledgerHash); | ||||
LedgerBlock block = ledger.getLatestBlock(); | LedgerBlock block = ledger.getLatestBlock(); | ||||
UserAccountSet userAccountSet = ledger.getUserAccountSet(block); | |||||
UserAccountQuery userAccountSet = ledger.getUserAccountSet(block); | |||||
return userAccountSet.getUser(address); | return userAccountSet.getUser(address); | ||||
} | } | ||||
@@ -249,7 +263,7 @@ public class LedgerQueryService implements BlockchainQueryService { | |||||
public AccountHeader getDataAccount(HashDigest ledgerHash, String address) { | public AccountHeader getDataAccount(HashDigest ledgerHash, String address) { | ||||
LedgerRepository ledger = ledgerService.getLedger(ledgerHash); | LedgerRepository ledger = ledgerService.getLedger(ledgerHash); | ||||
LedgerBlock block = ledger.getLatestBlock(); | LedgerBlock block = ledger.getLatestBlock(); | ||||
DataAccountSet dataAccountSet = ledger.getDataAccountSet(block); | |||||
DataAccountQuery dataAccountSet = ledger.getDataAccountSet(block); | |||||
return dataAccountSet.getDataAccount(Bytes.fromBase58(address)); | return dataAccountSet.getDataAccount(Bytes.fromBase58(address)); | ||||
} | } | ||||
@@ -260,7 +274,7 @@ public class LedgerQueryService implements BlockchainQueryService { | |||||
} | } | ||||
LedgerRepository ledger = ledgerService.getLedger(ledgerHash); | LedgerRepository ledger = ledgerService.getLedger(ledgerHash); | ||||
LedgerBlock block = ledger.getLatestBlock(); | LedgerBlock block = ledger.getLatestBlock(); | ||||
DataAccountSet dataAccountSet = ledger.getDataAccountSet(block); | |||||
DataAccountQuery dataAccountSet = ledger.getDataAccountSet(block); | |||||
DataAccount dataAccount = dataAccountSet.getDataAccount(Bytes.fromBase58(address)); | DataAccount dataAccount = dataAccountSet.getDataAccount(Bytes.fromBase58(address)); | ||||
KVDataEntry[] entries = new KVDataEntry[keys.length]; | KVDataEntry[] entries = new KVDataEntry[keys.length]; | ||||
@@ -308,7 +322,7 @@ public class LedgerQueryService implements BlockchainQueryService { | |||||
LedgerRepository ledger = ledgerService.getLedger(ledgerHash); | LedgerRepository ledger = ledgerService.getLedger(ledgerHash); | ||||
LedgerBlock block = ledger.getLatestBlock(); | LedgerBlock block = ledger.getLatestBlock(); | ||||
DataAccountSet dataAccountSet = ledger.getDataAccountSet(block); | |||||
DataAccountQuery dataAccountSet = ledger.getDataAccountSet(block); | |||||
DataAccount dataAccount = dataAccountSet.getDataAccount(Bytes.fromBase58(address)); | DataAccount dataAccount = dataAccountSet.getDataAccount(Bytes.fromBase58(address)); | ||||
KVDataEntry[] entries = new KVDataEntry[keys.length]; | KVDataEntry[] entries = new KVDataEntry[keys.length]; | ||||
@@ -339,7 +353,7 @@ public class LedgerQueryService implements BlockchainQueryService { | |||||
LedgerRepository ledger = ledgerService.getLedger(ledgerHash); | LedgerRepository ledger = ledgerService.getLedger(ledgerHash); | ||||
LedgerBlock block = ledger.getLatestBlock(); | LedgerBlock block = ledger.getLatestBlock(); | ||||
DataAccountSet dataAccountSet = ledger.getDataAccountSet(block); | |||||
DataAccountQuery dataAccountSet = ledger.getDataAccountSet(block); | |||||
DataAccount dataAccount = dataAccountSet.getDataAccount(Bytes.fromBase58(address)); | DataAccount dataAccount = dataAccountSet.getDataAccount(Bytes.fromBase58(address)); | ||||
int pages[] = QueryUtil.calFromIndexAndCount(fromIndex, count, (int) dataAccount.getDataEntriesTotalCount()); | int pages[] = QueryUtil.calFromIndexAndCount(fromIndex, count, (int) dataAccount.getDataEntriesTotalCount()); | ||||
@@ -351,7 +365,7 @@ public class LedgerQueryService implements BlockchainQueryService { | |||||
LedgerRepository ledger = ledgerService.getLedger(ledgerHash); | LedgerRepository ledger = ledgerService.getLedger(ledgerHash); | ||||
LedgerBlock block = ledger.getLatestBlock(); | LedgerBlock block = ledger.getLatestBlock(); | ||||
DataAccountSet dataAccountSet = ledger.getDataAccountSet(block); | |||||
DataAccountQuery dataAccountSet = ledger.getDataAccountSet(block); | |||||
DataAccount dataAccount = dataAccountSet.getDataAccount(Bytes.fromBase58(address)); | DataAccount dataAccount = dataAccountSet.getDataAccount(Bytes.fromBase58(address)); | ||||
return dataAccount.getDataEntriesTotalCount(); | return dataAccount.getDataEntriesTotalCount(); | ||||
@@ -361,7 +375,7 @@ public class LedgerQueryService implements BlockchainQueryService { | |||||
public ContractInfo getContract(HashDigest ledgerHash, String address) { | public ContractInfo getContract(HashDigest ledgerHash, String address) { | ||||
LedgerRepository ledger = ledgerService.getLedger(ledgerHash); | LedgerRepository ledger = ledgerService.getLedger(ledgerHash); | ||||
LedgerBlock block = ledger.getLatestBlock(); | LedgerBlock block = ledger.getLatestBlock(); | ||||
ContractAccountSet contractAccountSet = ledger.getContractAccountSet(block); | |||||
ContractAccountQuery contractAccountSet = ledger.getContractAccountSet(block); | |||||
return contractAccountSet.getContract(Bytes.fromBase58(address)); | return contractAccountSet.getContract(Bytes.fromBase58(address)); | ||||
} | } | ||||
@@ -369,7 +383,7 @@ public class LedgerQueryService implements BlockchainQueryService { | |||||
public AccountHeader[] getUsers(HashDigest ledgerHash, int fromIndex, int count) { | public AccountHeader[] getUsers(HashDigest ledgerHash, int fromIndex, int count) { | ||||
LedgerRepository ledger = ledgerService.getLedger(ledgerHash); | LedgerRepository ledger = ledgerService.getLedger(ledgerHash); | ||||
LedgerBlock block = ledger.getLatestBlock(); | LedgerBlock block = ledger.getLatestBlock(); | ||||
UserAccountSet userAccountSet = ledger.getUserAccountSet(block); | |||||
UserAccountQuery userAccountSet = ledger.getUserAccountSet(block); | |||||
int pages[] = QueryUtil.calFromIndexAndCount(fromIndex, count, (int) userAccountSet.getTotalCount()); | int pages[] = QueryUtil.calFromIndexAndCount(fromIndex, count, (int) userAccountSet.getTotalCount()); | ||||
return userAccountSet.getAccounts(pages[0], pages[1]); | return userAccountSet.getAccounts(pages[0], pages[1]); | ||||
} | } | ||||
@@ -378,7 +392,7 @@ public class LedgerQueryService implements BlockchainQueryService { | |||||
public AccountHeader[] getDataAccounts(HashDigest ledgerHash, int fromIndex, int count) { | public AccountHeader[] getDataAccounts(HashDigest ledgerHash, int fromIndex, int count) { | ||||
LedgerRepository ledger = ledgerService.getLedger(ledgerHash); | LedgerRepository ledger = ledgerService.getLedger(ledgerHash); | ||||
LedgerBlock block = ledger.getLatestBlock(); | LedgerBlock block = ledger.getLatestBlock(); | ||||
DataAccountSet dataAccountSet = ledger.getDataAccountSet(block); | |||||
DataAccountQuery dataAccountSet = ledger.getDataAccountSet(block); | |||||
int pages[] = QueryUtil.calFromIndexAndCount(fromIndex, count, (int) dataAccountSet.getTotalCount()); | int pages[] = QueryUtil.calFromIndexAndCount(fromIndex, count, (int) dataAccountSet.getTotalCount()); | ||||
return dataAccountSet.getAccounts(pages[0], pages[1]); | return dataAccountSet.getAccounts(pages[0], pages[1]); | ||||
} | } | ||||
@@ -387,15 +401,9 @@ public class LedgerQueryService implements BlockchainQueryService { | |||||
public AccountHeader[] getContractAccounts(HashDigest ledgerHash, int fromIndex, int count) { | public AccountHeader[] getContractAccounts(HashDigest ledgerHash, int fromIndex, int count) { | ||||
LedgerRepository ledger = ledgerService.getLedger(ledgerHash); | LedgerRepository ledger = ledgerService.getLedger(ledgerHash); | ||||
LedgerBlock block = ledger.getLatestBlock(); | LedgerBlock block = ledger.getLatestBlock(); | ||||
ContractAccountSet contractAccountSet = ledger.getContractAccountSet(block); | |||||
ContractAccountQuery contractAccountSet = ledger.getContractAccountSet(block); | |||||
int pages[] = QueryUtil.calFromIndexAndCount(fromIndex, count, (int) contractAccountSet.getTotalCount()); | int pages[] = QueryUtil.calFromIndexAndCount(fromIndex, count, (int) contractAccountSet.getTotalCount()); | ||||
return contractAccountSet.getAccounts(pages[0], pages[1]); | return contractAccountSet.getAccounts(pages[0], pages[1]); | ||||
} | } | ||||
private LedgerAdministration ledgerAdministration(HashDigest ledgerHash) { | |||||
LedgerRepository ledger = ledgerService.getLedger(ledgerHash); | |||||
LedgerBlock block = ledger.getLatestBlock(); | |||||
LedgerAdministration administration = ledger.getAdminAccount(block); | |||||
return administration; | |||||
} | |||||
} | } |
@@ -3,6 +3,7 @@ package com.jd.blockchain.ledger.core; | |||||
import java.io.Closeable; | import java.io.Closeable; | ||||
import com.jd.blockchain.crypto.HashDigest; | import com.jd.blockchain.crypto.HashDigest; | ||||
import com.jd.blockchain.ledger.LedgerAdminInfo; | |||||
import com.jd.blockchain.ledger.LedgerBlock; | import com.jd.blockchain.ledger.LedgerBlock; | ||||
public interface LedgerRepository extends Closeable { | public interface LedgerRepository extends Closeable { | ||||
@@ -51,23 +52,23 @@ public interface LedgerRepository extends Closeable { | |||||
*/ | */ | ||||
LedgerBlock getBlock(long height); | LedgerBlock getBlock(long height); | ||||
LedgerAdministration getAdminInfo(); | |||||
LedgerAdminInfo getAdminInfo(); | |||||
LedgerAdminInfo getAdminInfo(LedgerBlock block); | |||||
LedgerBlock getBlock(HashDigest hash); | LedgerBlock getBlock(HashDigest hash); | ||||
LedgerDataSet getDataSet(LedgerBlock block); | |||||
LedgerDataQuery getDataSet(LedgerBlock block); | |||||
TransactionSet getTransactionSet(LedgerBlock block); | TransactionSet getTransactionSet(LedgerBlock block); | ||||
LedgerAdminAccount getAdminAccount(LedgerBlock block); | |||||
UserAccountQuery getUserAccountSet(LedgerBlock block); | |||||
UserAccountSet getUserAccountSet(LedgerBlock block); | |||||
DataAccountQuery getDataAccountSet(LedgerBlock block); | |||||
DataAccountSet getDataAccountSet(LedgerBlock block); | |||||
ContractAccountQuery getContractAccountSet(LedgerBlock block); | |||||
ContractAccountSet getContractAccountSet(LedgerBlock block); | |||||
default LedgerDataSet getDataSet() { | |||||
default LedgerDataQuery getDataSet() { | |||||
return getDataSet(getLatestBlock()); | return getDataSet(getLatestBlock()); | ||||
} | } | ||||
@@ -75,19 +76,15 @@ public interface LedgerRepository extends Closeable { | |||||
return getTransactionSet(getLatestBlock()); | return getTransactionSet(getLatestBlock()); | ||||
} | } | ||||
default LedgerAdminAccount getAdminAccount() { | |||||
return getAdminAccount(getLatestBlock()); | |||||
} | |||||
default UserAccountSet getUserAccountSet() { | |||||
default UserAccountQuery getUserAccountSet() { | |||||
return getUserAccountSet(getLatestBlock()); | return getUserAccountSet(getLatestBlock()); | ||||
} | } | ||||
default DataAccountSet getDataAccountSet() { | |||||
default DataAccountQuery getDataAccountSet() { | |||||
return getDataAccountSet(getLatestBlock()); | return getDataAccountSet(getLatestBlock()); | ||||
} | } | ||||
default ContractAccountSet getContractAccountSet() { | |||||
default ContractAccountQuery getContractAccountSet() { | |||||
return getContractAccountSet(getLatestBlock()); | return getContractAccountSet(getLatestBlock()); | ||||
} | } | ||||
@@ -1,23 +1,17 @@ | |||||
package com.jd.blockchain.ledger.core.impl; | |||||
package com.jd.blockchain.ledger.core; | |||||
import com.jd.blockchain.binaryproto.BinaryProtocol; | import com.jd.blockchain.binaryproto.BinaryProtocol; | ||||
import com.jd.blockchain.crypto.Crypto; | import com.jd.blockchain.crypto.Crypto; | ||||
import com.jd.blockchain.crypto.HashDigest; | import com.jd.blockchain.crypto.HashDigest; | ||||
import com.jd.blockchain.crypto.HashFunction; | import com.jd.blockchain.crypto.HashFunction; | ||||
import com.jd.blockchain.ledger.*; | |||||
import com.jd.blockchain.ledger.core.AccountAccessPolicy; | |||||
import com.jd.blockchain.ledger.core.ContractAccountSet; | |||||
import com.jd.blockchain.ledger.core.DataAccountSet; | |||||
import com.jd.blockchain.ledger.core.LedgerAdminAccount; | |||||
import com.jd.blockchain.ledger.core.LedgerAdministration; | |||||
import com.jd.blockchain.ledger.core.LedgerConsts; | |||||
import com.jd.blockchain.ledger.core.LedgerDataSet; | |||||
import com.jd.blockchain.ledger.core.LedgerEditor; | |||||
import com.jd.blockchain.ledger.core.LedgerRepository; | |||||
import com.jd.blockchain.ledger.core.LedgerTransactionContext; | |||||
import com.jd.blockchain.ledger.core.SettingContext; | |||||
import com.jd.blockchain.ledger.core.TransactionSet; | |||||
import com.jd.blockchain.ledger.core.UserAccountSet; | |||||
import com.jd.blockchain.ledger.BlockBody; | |||||
import com.jd.blockchain.ledger.CryptoSetting; | |||||
import com.jd.blockchain.ledger.LedgerAdminInfo; | |||||
import com.jd.blockchain.ledger.LedgerBlock; | |||||
import com.jd.blockchain.ledger.LedgerDataSnapshot; | |||||
import com.jd.blockchain.ledger.LedgerInitSetting; | |||||
import com.jd.blockchain.ledger.LedgerSettings; | |||||
import com.jd.blockchain.ledger.TransactionRequest; | |||||
import com.jd.blockchain.storage.service.ExPolicyKVStorage; | import com.jd.blockchain.storage.service.ExPolicyKVStorage; | ||||
import com.jd.blockchain.storage.service.VersioningKVStorage; | import com.jd.blockchain.storage.service.VersioningKVStorage; | ||||
import com.jd.blockchain.utils.Bytes; | import com.jd.blockchain.utils.Bytes; | ||||
@@ -36,7 +30,7 @@ import com.jd.blockchain.utils.codec.Base58Utils; | |||||
* @author huanghaiquan | * @author huanghaiquan | ||||
* | * | ||||
*/ | */ | ||||
public class LedgerRepositoryImpl implements LedgerRepository { | |||||
class LedgerRepositoryImpl implements LedgerRepository { | |||||
private static final Bytes LEDGER_PREFIX = Bytes.fromString("IDX" + LedgerConsts.KEY_SEPERATOR); | private static final Bytes LEDGER_PREFIX = Bytes.fromString("IDX" + LedgerConsts.KEY_SEPERATOR); | ||||
@@ -80,6 +74,8 @@ public class LedgerRepositoryImpl implements LedgerRepository { | |||||
if (getLatestBlockHeight() < 0) { | if (getLatestBlockHeight() < 0) { | ||||
throw new RuntimeException("Ledger doesn't exist!"); | throw new RuntimeException("Ledger doesn't exist!"); | ||||
} | } | ||||
retrieveLatestState(); | |||||
} | } | ||||
/* | /* | ||||
@@ -110,25 +106,27 @@ public class LedgerRepositoryImpl implements LedgerRepository { | |||||
@Override | @Override | ||||
public LedgerBlock getLatestBlock() { | public LedgerBlock getLatestBlock() { | ||||
LedgerState state = getLatestState(); | |||||
return state.block; | |||||
return latestState.block; | |||||
} | } | ||||
private LedgerState getLatestState() { | |||||
LedgerState state = latestState; | |||||
if (state == null) { | |||||
LedgerBlock latestBlock = innerGetBlock(innerGetLatestBlockHeight()); | |||||
state = new LedgerState(latestBlock); | |||||
latestState = state; | |||||
} | |||||
return state; | |||||
/** | |||||
* 重新检索加载最新的状态; | |||||
* | |||||
* @return | |||||
*/ | |||||
private LedgerState retrieveLatestState() { | |||||
LedgerBlock latestBlock = innerGetBlock(innerGetLatestBlockHeight()); | |||||
LedgerDataset ledgerDataset = innerGetLedgerDataset(latestBlock); | |||||
TransactionSet txSet = loadTransactionSet(latestBlock.getTransactionSetHash(), | |||||
ledgerDataset.getAdminDataset().getSettings().getCryptoSetting(), keyPrefix, exPolicyStorage, | |||||
versioningStorage, true); | |||||
this.latestState = new LedgerState(latestBlock, ledgerDataset, txSet); | |||||
return latestState; | |||||
} | } | ||||
@Override | @Override | ||||
public LedgerBlock retrieveLatestBlock() { | public LedgerBlock retrieveLatestBlock() { | ||||
LedgerBlock latestBlock = innerGetBlock(innerGetLatestBlockHeight()); | |||||
latestState = new LedgerState(latestBlock); | |||||
return latestBlock; | |||||
return retrieveLatestState().block; | |||||
} | } | ||||
@Override | @Override | ||||
@@ -187,7 +185,7 @@ public class LedgerRepositoryImpl implements LedgerRepository { | |||||
if (height < 0) { | if (height < 0) { | ||||
return null; | return null; | ||||
} | } | ||||
return innerGetBlock(getBlockHash(height)); | |||||
return innerGetBlock(innerGetBlockHash(height)); | |||||
} | } | ||||
@Override | @Override | ||||
@@ -209,26 +207,18 @@ public class LedgerRepositoryImpl implements LedgerRepository { | |||||
throw new RuntimeException("Block hash not equals to it's storage key!"); | throw new RuntimeException("Block hash not equals to it's storage key!"); | ||||
} | } | ||||
// verify hash; | |||||
// boolean requiredVerifyHash = | |||||
// adminAccount.getMetadata().getSetting().getCryptoSetting().getAutoVerifyHash(); | |||||
// TODO: 未实现从配置中加载是否校验 Hash 的设置; | |||||
if (SettingContext.queryingSettings().verifyHash()) { | |||||
byte[] blockBodyBytes = null; | |||||
if (block.getHeight() == 0) { | |||||
// 计算创世区块的 hash 时,不包括 ledgerHash 字段; | |||||
block.setLedgerHash(null); | |||||
blockBodyBytes = BinaryProtocol.encode(block, BlockBody.class); | |||||
// 恢复; | |||||
block.setLedgerHash(block.getHash()); | |||||
} else { | |||||
blockBodyBytes = BinaryProtocol.encode(block, BlockBody.class); | |||||
} | |||||
HashFunction hashFunc = Crypto.getHashFunction(blockHash.getAlgorithm()); | |||||
boolean pass = hashFunc.verify(blockHash, blockBodyBytes); | |||||
if (!pass) { | |||||
throw new RuntimeException("Block hash verification fail!"); | |||||
} | |||||
// verify block hash; | |||||
byte[] blockBodyBytes = null; | |||||
if (block.getHeight() == 0) { | |||||
// 计算创世区块的 hash 时,不包括 ledgerHash 字段; | |||||
blockBodyBytes = BinaryProtocol.encode(block, BlockBody.class); | |||||
} else { | |||||
blockBodyBytes = BinaryProtocol.encode(block, BlockBody.class); | |||||
} | |||||
HashFunction hashFunc = Crypto.getHashFunction(blockHash.getAlgorithm()); | |||||
boolean pass = hashFunc.verify(blockHash, blockBodyBytes); | |||||
if (!pass) { | |||||
throw new RuntimeException("Block hash verification fail!"); | |||||
} | } | ||||
// verify height; | // verify height; | ||||
@@ -243,9 +233,18 @@ public class LedgerRepositoryImpl implements LedgerRepository { | |||||
return block; | return block; | ||||
} | } | ||||
/** | |||||
* 获取最新区块的账本参数; | |||||
* | |||||
* @return | |||||
*/ | |||||
private LedgerSettings getLatestSettings() { | |||||
return getAdminInfo().getSettings(); | |||||
} | |||||
@Override | @Override | ||||
public LedgerAdministration getAdminInfo() { | |||||
return getAdminAccount(getLatestBlock()); | |||||
public LedgerAdminInfo getAdminInfo() { | |||||
return getAdminInfo(getLatestBlock()); | |||||
} | } | ||||
private LedgerBlock deserialize(byte[] blockBytes) { | private LedgerBlock deserialize(byte[] blockBytes) { | ||||
@@ -255,140 +254,96 @@ public class LedgerRepositoryImpl implements LedgerRepository { | |||||
@Override | @Override | ||||
public TransactionSet getTransactionSet(LedgerBlock block) { | public TransactionSet getTransactionSet(LedgerBlock block) { | ||||
long height = getLatestBlockHeight(); | long height = getLatestBlockHeight(); | ||||
TransactionSet transactionSet = null; | |||||
if (height == block.getHeight()) { | if (height == block.getHeight()) { | ||||
// 缓存读; | |||||
LedgerState state = getLatestState(); | |||||
transactionSet = state.transactionSet; | |||||
if (transactionSet == null) { | |||||
LedgerAdminAccount adminAccount = getAdminAccount(block); | |||||
transactionSet = loadTransactionSet(block.getTransactionSetHash(), | |||||
adminAccount.getMetadata().getSetting().getCryptoSetting(), keyPrefix, exPolicyStorage, | |||||
versioningStorage, true); | |||||
state.transactionSet = transactionSet; | |||||
} | |||||
return transactionSet; | |||||
// 从缓存中返回最新区块的数据集; | |||||
return latestState.getTransactionSet(); | |||||
} | } | ||||
LedgerAdminAccount adminAccount = getAdminAccount(block); | |||||
LedgerAdminInfo adminAccount = getAdminInfo(block); | |||||
// All of existing block is readonly; | // All of existing block is readonly; | ||||
return loadTransactionSet(block.getTransactionSetHash(), | |||||
adminAccount.getMetadata().getSetting().getCryptoSetting(), keyPrefix, exPolicyStorage, | |||||
versioningStorage, true); | |||||
return loadTransactionSet(block.getTransactionSetHash(), adminAccount.getSettings().getCryptoSetting(), | |||||
keyPrefix, exPolicyStorage, versioningStorage, true); | |||||
} | } | ||||
@Override | @Override | ||||
public LedgerAdminAccount getAdminAccount(LedgerBlock block) { | |||||
public LedgerAdminDataset getAdminInfo(LedgerBlock block) { | |||||
long height = getLatestBlockHeight(); | long height = getLatestBlockHeight(); | ||||
LedgerAdminAccount adminAccount = null; | |||||
if (height == block.getHeight()) { | if (height == block.getHeight()) { | ||||
// 缓存读; | |||||
LedgerState state = getLatestState(); | |||||
adminAccount = state.adminAccount; | |||||
if (adminAccount == null) { | |||||
adminAccount = new LedgerAdminAccount(block.getAdminAccountHash(), keyPrefix, exPolicyStorage, | |||||
versioningStorage, true); | |||||
state.adminAccount = adminAccount; | |||||
} | |||||
return adminAccount; | |||||
return latestState.getAdminDataset(); | |||||
} | } | ||||
return new LedgerAdminAccount(block.getAdminAccountHash(), keyPrefix, exPolicyStorage, versioningStorage, true); | |||||
return createAdminDataset(block); | |||||
} | |||||
private LedgerAdminDataset createAdminDataset(LedgerBlock block) { | |||||
return new LedgerAdminDataset(block.getAdminAccountHash(), keyPrefix, exPolicyStorage, versioningStorage, true); | |||||
} | } | ||||
@Override | @Override | ||||
public UserAccountSet getUserAccountSet(LedgerBlock block) { | |||||
public UserAccountQuery getUserAccountSet(LedgerBlock block) { | |||||
long height = getLatestBlockHeight(); | long height = getLatestBlockHeight(); | ||||
UserAccountSet userAccountSet = null; | |||||
if (height == block.getHeight()) { | if (height == block.getHeight()) { | ||||
// 缓存读; | |||||
LedgerState state = getLatestState(); | |||||
userAccountSet = state.userAccountSet; | |||||
if (userAccountSet == null) { | |||||
LedgerAdminAccount adminAccount = getAdminAccount(block); | |||||
userAccountSet = loadUserAccountSet(block.getUserAccountSetHash(), | |||||
adminAccount.getPreviousSetting().getCryptoSetting(), keyPrefix, exPolicyStorage, | |||||
versioningStorage, true); | |||||
state.userAccountSet = userAccountSet; | |||||
} | |||||
return userAccountSet; | |||||
return latestState.getUserAccountSet(); | |||||
} | } | ||||
LedgerAdminAccount adminAccount = getAdminAccount(block); | |||||
return loadUserAccountSet(block.getUserAccountSetHash(), adminAccount.getPreviousSetting().getCryptoSetting(), | |||||
keyPrefix, exPolicyStorage, versioningStorage, true); | |||||
LedgerAdminDataset adminAccount = getAdminInfo(block); | |||||
return createUserAccountSet(block, adminAccount.getSettings().getCryptoSetting()); | |||||
} | |||||
private UserAccountSet createUserAccountSet(LedgerBlock block, CryptoSetting cryptoSetting) { | |||||
return loadUserAccountSet(block.getUserAccountSetHash(), cryptoSetting, keyPrefix, exPolicyStorage, | |||||
versioningStorage, true); | |||||
} | } | ||||
@Override | @Override | ||||
public DataAccountSet getDataAccountSet(LedgerBlock block) { | |||||
public DataAccountQuery getDataAccountSet(LedgerBlock block) { | |||||
long height = getLatestBlockHeight(); | long height = getLatestBlockHeight(); | ||||
DataAccountSet dataAccountSet = null; | |||||
if (height == block.getHeight()) { | if (height == block.getHeight()) { | ||||
// 缓存读; | |||||
LedgerState state = getLatestState(); | |||||
dataAccountSet = state.dataAccountSet; | |||||
if (dataAccountSet == null) { | |||||
LedgerAdminAccount adminAccount = getAdminAccount(block); | |||||
dataAccountSet = loadDataAccountSet(block.getDataAccountSetHash(), | |||||
adminAccount.getPreviousSetting().getCryptoSetting(), keyPrefix, exPolicyStorage, | |||||
versioningStorage, true); | |||||
state.dataAccountSet = dataAccountSet; | |||||
} | |||||
return dataAccountSet; | |||||
return latestState.getDataAccountSet(); | |||||
} | } | ||||
LedgerAdminAccount adminAccount = getAdminAccount(block); | |||||
return loadDataAccountSet(block.getDataAccountSetHash(), adminAccount.getPreviousSetting().getCryptoSetting(), | |||||
keyPrefix, exPolicyStorage, versioningStorage, true); | |||||
LedgerAdminDataset adminAccount = getAdminInfo(block); | |||||
return createDataAccountSet(block, adminAccount.getSettings().getCryptoSetting()); | |||||
} | |||||
private DataAccountSet createDataAccountSet(LedgerBlock block, CryptoSetting setting) { | |||||
return loadDataAccountSet(block.getDataAccountSetHash(), setting, keyPrefix, exPolicyStorage, versioningStorage, | |||||
true); | |||||
} | } | ||||
@Override | @Override | ||||
public ContractAccountSet getContractAccountSet(LedgerBlock block) { | |||||
public ContractAccountQuery getContractAccountSet(LedgerBlock block) { | |||||
long height = getLatestBlockHeight(); | long height = getLatestBlockHeight(); | ||||
ContractAccountSet contractAccountSet = null; | |||||
if (height == block.getHeight()) { | if (height == block.getHeight()) { | ||||
// 缓存读; | |||||
LedgerState state = getLatestState(); | |||||
contractAccountSet = state.contractAccountSet; | |||||
if (contractAccountSet == null) { | |||||
LedgerAdminAccount adminAccount = getAdminAccount(block); | |||||
contractAccountSet = loadContractAccountSet(block.getContractAccountSetHash(), | |||||
adminAccount.getPreviousSetting().getCryptoSetting(), keyPrefix, exPolicyStorage, | |||||
versioningStorage, true); | |||||
state.contractAccountSet = contractAccountSet; | |||||
} | |||||
return contractAccountSet; | |||||
return latestState.getContractAccountSet(); | |||||
} | } | ||||
LedgerAdminAccount adminAccount = getAdminAccount(block); | |||||
return loadContractAccountSet(block.getContractAccountSetHash(), | |||||
adminAccount.getPreviousSetting().getCryptoSetting(), keyPrefix, exPolicyStorage, versioningStorage, | |||||
true); | |||||
LedgerAdminDataset adminAccount = getAdminInfo(block); | |||||
return createContractAccountSet(block, adminAccount.getSettings().getCryptoSetting()); | |||||
} | |||||
private ContractAccountSet createContractAccountSet(LedgerBlock block, CryptoSetting cryptoSetting) { | |||||
return loadContractAccountSet(block.getContractAccountSetHash(), cryptoSetting, keyPrefix, exPolicyStorage, | |||||
versioningStorage, true); | |||||
} | } | ||||
@Override | @Override | ||||
public LedgerDataSet getDataSet(LedgerBlock block) { | |||||
public LedgerDataset getDataSet(LedgerBlock block) { | |||||
long height = getLatestBlockHeight(); | long height = getLatestBlockHeight(); | ||||
LedgerDataSet ledgerDataSet = null; | |||||
if (height == block.getHeight()) { | if (height == block.getHeight()) { | ||||
// 缓存读; | |||||
LedgerState state = getLatestState(); | |||||
ledgerDataSet = state.ledgerDataSet; | |||||
if (ledgerDataSet == null) { | |||||
ledgerDataSet = innerDataSet(block); | |||||
state.ledgerDataSet = ledgerDataSet; | |||||
} | |||||
return ledgerDataSet; | |||||
return latestState.getLedgerDataset(); | |||||
} | } | ||||
// All of existing block is readonly; | // All of existing block is readonly; | ||||
return innerDataSet(block); | |||||
return innerGetLedgerDataset(block); | |||||
} | } | ||||
private LedgerDataSet innerDataSet(LedgerBlock block) { | |||||
LedgerAdminAccount adminAccount = getAdminAccount(block); | |||||
UserAccountSet userAccountSet = getUserAccountSet(block); | |||||
DataAccountSet dataAccountSet = getDataAccountSet(block); | |||||
ContractAccountSet contractAccountSet = getContractAccountSet(block); | |||||
return new LedgerDataSetImpl(adminAccount, userAccountSet, dataAccountSet, contractAccountSet, true); | |||||
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); | |||||
return new LedgerDataset(adminDataset, userAccountSet, dataAccountSet, contractAccountSet, true); | |||||
} | } | ||||
@Override | @Override | ||||
@@ -401,9 +356,8 @@ public class LedgerRepositoryImpl implements LedgerRepository { | |||||
"A new block is in process, cann't create another one until it finish by committing or canceling."); | "A new block is in process, cann't create another one until it finish by committing or canceling."); | ||||
} | } | ||||
LedgerBlock previousBlock = getLatestBlock(); | LedgerBlock previousBlock = getLatestBlock(); | ||||
LedgerTransactionalEditor editor = LedgerTransactionalEditor.createEditor(previousBlock, | |||||
getAdminInfo().getMetadata().getSetting(), keyPrefix, exPolicyStorage, | |||||
versioningStorage); | |||||
LedgerTransactionalEditor editor = LedgerTransactionalEditor.createEditor(previousBlock, getLatestSettings(), | |||||
keyPrefix, exPolicyStorage, versioningStorage); | |||||
NewBlockCommittingMonitor committingMonitor = new NewBlockCommittingMonitor(editor, this); | NewBlockCommittingMonitor committingMonitor = new NewBlockCommittingMonitor(editor, this); | ||||
this.nextBlockEditor = committingMonitor; | this.nextBlockEditor = committingMonitor; | ||||
return committingMonitor; | return committingMonitor; | ||||
@@ -426,64 +380,39 @@ public class LedgerRepositoryImpl implements LedgerRepository { | |||||
} | } | ||||
static Bytes encodeLedgerIndexKey(HashDigest ledgerHash) { | static Bytes encodeLedgerIndexKey(HashDigest ledgerHash) { | ||||
// return LEDGER_PREFIX + Base58Utils.encode(ledgerHash.toBytes()); | |||||
// return new Bytes(ledgerHash.toBytes()).concatTo(LEDGER_PREFIX); | |||||
return LEDGER_PREFIX.concat(ledgerHash); | return LEDGER_PREFIX.concat(ledgerHash); | ||||
} | } | ||||
static Bytes encodeBlockStorageKey(HashDigest blockHash) { | static Bytes encodeBlockStorageKey(HashDigest blockHash) { | ||||
// String key = ByteArray.toBase58(blockHash.toBytes()); | |||||
// return BLOCK_PREFIX + key; | |||||
return BLOCK_PREFIX.concat(blockHash); | return BLOCK_PREFIX.concat(blockHash); | ||||
} | } | ||||
static LedgerDataSetImpl newDataSet(LedgerInitSetting initSetting, String keyPrefix, | |||||
static LedgerDataset newDataSet(LedgerInitSetting initSetting, String keyPrefix, | |||||
ExPolicyKVStorage ledgerExStorage, VersioningKVStorage ledgerVerStorage) { | ExPolicyKVStorage ledgerExStorage, VersioningKVStorage ledgerVerStorage) { | ||||
LedgerAdminAccount adminAccount = new LedgerAdminAccount(initSetting, keyPrefix, ledgerExStorage, | |||||
LedgerAdminDataset adminAccount = new LedgerAdminDataset(initSetting, keyPrefix, ledgerExStorage, | |||||
ledgerVerStorage); | ledgerVerStorage); | ||||
String usersetKeyPrefix = keyPrefix + USER_SET_PREFIX; | String usersetKeyPrefix = keyPrefix + USER_SET_PREFIX; | ||||
String datasetKeyPrefix = keyPrefix + DATA_SET_PREFIX; | String datasetKeyPrefix = keyPrefix + DATA_SET_PREFIX; | ||||
String contractsetKeyPrefix = keyPrefix + CONTRACT_SET_PREFIX; | String contractsetKeyPrefix = keyPrefix + CONTRACT_SET_PREFIX; | ||||
// String txsetKeyPrefix = keyPrefix + TRANSACTION_SET_PREFIX; | |||||
// UserAccountSet userAccountSet = new | |||||
// UserAccountSet(adminAccount.getSetting().getCryptoSetting(), | |||||
// PrefixAppender.prefix(USER_SET_PREFIX, ledgerExStorage), | |||||
// PrefixAppender.prefix(USER_SET_PREFIX, ledgerVerStorage), | |||||
// DEFAULT_ACCESS_POLICY); | |||||
UserAccountSet userAccountSet = new UserAccountSet(adminAccount.getSetting().getCryptoSetting(), | |||||
UserAccountSet userAccountSet = new UserAccountSet(adminAccount.getSettings().getCryptoSetting(), | |||||
usersetKeyPrefix, ledgerExStorage, ledgerVerStorage, DEFAULT_ACCESS_POLICY); | usersetKeyPrefix, ledgerExStorage, ledgerVerStorage, DEFAULT_ACCESS_POLICY); | ||||
// DataAccountSet dataAccountSet = new | |||||
// DataAccountSet(adminAccount.getSetting().getCryptoSetting(), | |||||
// PrefixAppender.prefix(DATA_SET_PREFIX, ledgerExStorage), | |||||
// PrefixAppender.prefix(DATA_SET_PREFIX, ledgerVerStorage), | |||||
// DEFAULT_ACCESS_POLICY); | |||||
DataAccountSet dataAccountSet = new DataAccountSet(adminAccount.getSetting().getCryptoSetting(), | |||||
DataAccountSet dataAccountSet = new DataAccountSet(adminAccount.getSettings().getCryptoSetting(), | |||||
datasetKeyPrefix, ledgerExStorage, ledgerVerStorage, DEFAULT_ACCESS_POLICY); | datasetKeyPrefix, ledgerExStorage, ledgerVerStorage, DEFAULT_ACCESS_POLICY); | ||||
// ContractAccountSet contractAccountSet = new | |||||
// ContractAccountSet(adminAccount.getSetting().getCryptoSetting(), | |||||
// PrefixAppender.prefix(CONTRACT_SET_PREFIX, ledgerExStorage), | |||||
// PrefixAppender.prefix(CONTRACT_SET_PREFIX, ledgerVerStorage), | |||||
// DEFAULT_ACCESS_POLICY); | |||||
ContractAccountSet contractAccountSet = new ContractAccountSet(adminAccount.getSetting().getCryptoSetting(), | |||||
ContractAccountSet contractAccountSet = new ContractAccountSet(adminAccount.getSettings().getCryptoSetting(), | |||||
contractsetKeyPrefix, ledgerExStorage, ledgerVerStorage, DEFAULT_ACCESS_POLICY); | contractsetKeyPrefix, ledgerExStorage, ledgerVerStorage, DEFAULT_ACCESS_POLICY); | ||||
LedgerDataSetImpl newDataSet = new LedgerDataSetImpl(adminAccount, userAccountSet, dataAccountSet, | |||||
LedgerDataset newDataSet = new LedgerDataset(adminAccount, userAccountSet, dataAccountSet, | |||||
contractAccountSet, false); | contractAccountSet, false); | ||||
return newDataSet; | return newDataSet; | ||||
} | } | ||||
static TransactionSet newTransactionSet(LedgerSetting ledgerSetting, String keyPrefix, | |||||
static TransactionSet newTransactionSet(LedgerSettings ledgerSetting, String keyPrefix, | |||||
ExPolicyKVStorage ledgerExStorage, VersioningKVStorage ledgerVerStorage) { | ExPolicyKVStorage ledgerExStorage, VersioningKVStorage ledgerVerStorage) { | ||||
// TransactionSet transactionSet = new | |||||
// TransactionSet(ledgerSetting.getCryptoSetting(), | |||||
// PrefixAppender.prefix(TRANSACTION_SET_PREFIX, ledgerExStorage), | |||||
// PrefixAppender.prefix(TRANSACTION_SET_PREFIX, ledgerVerStorage)); | |||||
String txsetKeyPrefix = keyPrefix + TRANSACTION_SET_PREFIX; | String txsetKeyPrefix = keyPrefix + TRANSACTION_SET_PREFIX; | ||||
@@ -492,13 +421,11 @@ public class LedgerRepositoryImpl implements LedgerRepository { | |||||
return transactionSet; | return transactionSet; | ||||
} | } | ||||
static LedgerDataSetImpl loadDataSet(LedgerDataSnapshot dataSnapshot, String keyPrefix, | |||||
static LedgerDataset loadDataSet(LedgerDataSnapshot dataSnapshot, CryptoSetting cryptoSetting, String keyPrefix, | |||||
ExPolicyKVStorage ledgerExStorage, VersioningKVStorage ledgerVerStorage, boolean readonly) { | ExPolicyKVStorage ledgerExStorage, VersioningKVStorage ledgerVerStorage, boolean readonly) { | ||||
LedgerAdminAccount adminAccount = new LedgerAdminAccount(dataSnapshot.getAdminAccountHash(), keyPrefix, | |||||
LedgerAdminDataset adminAccount = new LedgerAdminDataset(dataSnapshot.getAdminAccountHash(), keyPrefix, | |||||
ledgerExStorage, ledgerVerStorage, readonly); | ledgerExStorage, ledgerVerStorage, readonly); | ||||
CryptoSetting cryptoSetting = adminAccount.getPreviousSetting().getCryptoSetting(); | |||||
UserAccountSet userAccountSet = loadUserAccountSet(dataSnapshot.getUserAccountSetHash(), cryptoSetting, | UserAccountSet userAccountSet = loadUserAccountSet(dataSnapshot.getUserAccountSetHash(), cryptoSetting, | ||||
keyPrefix, ledgerExStorage, ledgerVerStorage, readonly); | keyPrefix, ledgerExStorage, ledgerVerStorage, readonly); | ||||
@@ -508,7 +435,7 @@ public class LedgerRepositoryImpl implements LedgerRepository { | |||||
ContractAccountSet contractAccountSet = loadContractAccountSet(dataSnapshot.getContractAccountSetHash(), | ContractAccountSet contractAccountSet = loadContractAccountSet(dataSnapshot.getContractAccountSetHash(), | ||||
cryptoSetting, keyPrefix, ledgerExStorage, ledgerVerStorage, readonly); | cryptoSetting, keyPrefix, ledgerExStorage, ledgerVerStorage, readonly); | ||||
LedgerDataSetImpl dataset = new LedgerDataSetImpl(adminAccount, userAccountSet, dataAccountSet, | |||||
LedgerDataset dataset = new LedgerDataset(adminAccount, userAccountSet, dataAccountSet, | |||||
contractAccountSet, readonly); | contractAccountSet, readonly); | ||||
return dataset; | return dataset; | ||||
@@ -517,10 +444,6 @@ public class LedgerRepositoryImpl implements LedgerRepository { | |||||
static UserAccountSet loadUserAccountSet(HashDigest userAccountSetHash, CryptoSetting cryptoSetting, | static UserAccountSet loadUserAccountSet(HashDigest userAccountSetHash, CryptoSetting cryptoSetting, | ||||
String keyPrefix, ExPolicyKVStorage ledgerExStorage, VersioningKVStorage ledgerVerStorage, | String keyPrefix, ExPolicyKVStorage ledgerExStorage, VersioningKVStorage ledgerVerStorage, | ||||
boolean readonly) { | boolean readonly) { | ||||
// return new UserAccountSet(userAccountSetHash, cryptoSetting, | |||||
// PrefixAppender.prefix(USER_SET_PREFIX, ledgerExStorage), | |||||
// PrefixAppender.prefix(USER_SET_PREFIX, ledgerVerStorage), readonly, | |||||
// DEFAULT_ACCESS_POLICY); | |||||
String usersetKeyPrefix = keyPrefix + USER_SET_PREFIX; | String usersetKeyPrefix = keyPrefix + USER_SET_PREFIX; | ||||
return new UserAccountSet(userAccountSetHash, cryptoSetting, usersetKeyPrefix, ledgerExStorage, | return new UserAccountSet(userAccountSetHash, cryptoSetting, usersetKeyPrefix, ledgerExStorage, | ||||
@@ -530,10 +453,6 @@ public class LedgerRepositoryImpl implements LedgerRepository { | |||||
static DataAccountSet loadDataAccountSet(HashDigest dataAccountSetHash, CryptoSetting cryptoSetting, | static DataAccountSet loadDataAccountSet(HashDigest dataAccountSetHash, CryptoSetting cryptoSetting, | ||||
String keyPrefix, ExPolicyKVStorage ledgerExStorage, VersioningKVStorage ledgerVerStorage, | String keyPrefix, ExPolicyKVStorage ledgerExStorage, VersioningKVStorage ledgerVerStorage, | ||||
boolean readonly) { | boolean readonly) { | ||||
// return new DataAccountSet(dataAccountSetHash, cryptoSetting, | |||||
// PrefixAppender.prefix(DATA_SET_PREFIX, ledgerExStorage, | |||||
// PrefixAppender.prefix(DATA_SET_PREFIX, ledgerVerStorage), readonly, | |||||
// DEFAULT_ACCESS_POLICY); | |||||
String datasetKeyPrefix = keyPrefix + DATA_SET_PREFIX; | String datasetKeyPrefix = keyPrefix + DATA_SET_PREFIX; | ||||
return new DataAccountSet(dataAccountSetHash, cryptoSetting, datasetKeyPrefix, ledgerExStorage, | return new DataAccountSet(dataAccountSetHash, cryptoSetting, datasetKeyPrefix, ledgerExStorage, | ||||
@@ -543,10 +462,6 @@ public class LedgerRepositoryImpl implements LedgerRepository { | |||||
static ContractAccountSet loadContractAccountSet(HashDigest contractAccountSetHash, CryptoSetting cryptoSetting, | static ContractAccountSet loadContractAccountSet(HashDigest contractAccountSetHash, CryptoSetting cryptoSetting, | ||||
String keyPrefix, ExPolicyKVStorage ledgerExStorage, VersioningKVStorage ledgerVerStorage, | String keyPrefix, ExPolicyKVStorage ledgerExStorage, VersioningKVStorage ledgerVerStorage, | ||||
boolean readonly) { | boolean readonly) { | ||||
// return new ContractAccountSet(contractAccountSetHash, cryptoSetting, | |||||
// PrefixAppender.prefix(CONTRACT_SET_PREFIX, ledgerExStorage, | |||||
// PrefixAppender.prefix(CONTRACT_SET_PREFIX, ledgerVerStorage), readonly, | |||||
// DEFAULT_ACCESS_POLICY); | |||||
String contractsetKeyPrefix = keyPrefix + CONTRACT_SET_PREFIX; | String contractsetKeyPrefix = keyPrefix + CONTRACT_SET_PREFIX; | ||||
return new ContractAccountSet(contractAccountSetHash, cryptoSetting, contractsetKeyPrefix, ledgerExStorage, | return new ContractAccountSet(contractAccountSetHash, cryptoSetting, contractsetKeyPrefix, ledgerExStorage, | ||||
@@ -555,9 +470,6 @@ public class LedgerRepositoryImpl implements LedgerRepository { | |||||
static TransactionSet loadTransactionSet(HashDigest txsetHash, CryptoSetting cryptoSetting, String keyPrefix, | static TransactionSet loadTransactionSet(HashDigest txsetHash, CryptoSetting cryptoSetting, String keyPrefix, | ||||
ExPolicyKVStorage ledgerExStorage, VersioningKVStorage ledgerVerStorage, boolean readonly) { | ExPolicyKVStorage ledgerExStorage, VersioningKVStorage ledgerVerStorage, boolean readonly) { | ||||
// return new TransactionSet(txsetHash, cryptoSetting, | |||||
// PrefixAppender.prefix(TRANSACTION_SET_PREFIX, ledgerExStorage), | |||||
// PrefixAppender.prefix(TRANSACTION_SET_PREFIX, ledgerVerStorage), readonly); | |||||
String txsetKeyPrefix = keyPrefix + TRANSACTION_SET_PREFIX; | String txsetKeyPrefix = keyPrefix + TRANSACTION_SET_PREFIX; | ||||
return new TransactionSet(txsetHash, cryptoSetting, txsetKeyPrefix, ledgerExStorage, ledgerVerStorage, | return new TransactionSet(txsetHash, cryptoSetting, txsetKeyPrefix, ledgerExStorage, ledgerVerStorage, | ||||
@@ -586,6 +498,16 @@ public class LedgerRepositoryImpl implements LedgerRepository { | |||||
return editor.getBlockHeight(); | return editor.getBlockHeight(); | ||||
} | } | ||||
@Override | |||||
public LedgerDataset getLedgerDataset() { | |||||
return editor.getLedgerDataset(); | |||||
} | |||||
@Override | |||||
public TransactionSet getTransactionSet() { | |||||
return editor.getTransactionSet(); | |||||
} | |||||
@Override | @Override | ||||
public LedgerTransactionContext newTransaction(TransactionRequest txRequest) { | public LedgerTransactionContext newTransaction(TransactionRequest txRequest) { | ||||
return editor.newTransaction(txRequest); | return editor.newTransaction(txRequest); | ||||
@@ -601,7 +523,8 @@ public class LedgerRepositoryImpl implements LedgerRepository { | |||||
try { | try { | ||||
editor.commit(); | editor.commit(); | ||||
LedgerBlock latestBlock = editor.getCurrentBlock(); | LedgerBlock latestBlock = editor.getCurrentBlock(); | ||||
ledgerRepo.latestState = new LedgerState(latestBlock); | |||||
ledgerRepo.latestState = new LedgerState(latestBlock, editor.getLedgerDataset(), | |||||
editor.getTransactionSet()); | |||||
} finally { | } finally { | ||||
ledgerRepo.nextBlockEditor = null; | ledgerRepo.nextBlockEditor = null; | ||||
} | } | ||||
@@ -628,20 +551,39 @@ public class LedgerRepositoryImpl implements LedgerRepository { | |||||
private final LedgerBlock block; | private final LedgerBlock block; | ||||
private volatile LedgerAdminAccount adminAccount; | |||||
private final TransactionSet transactionSet; | |||||
private volatile UserAccountSet userAccountSet; | |||||
private final LedgerDataset ledgerDataset; | |||||
private volatile DataAccountSet dataAccountSet; | |||||
public LedgerState(LedgerBlock block, LedgerDataset ledgerDataset, TransactionSet transactionSet) { | |||||
this.block = block; | |||||
this.ledgerDataset = ledgerDataset; | |||||
this.transactionSet = transactionSet; | |||||
private volatile ContractAccountSet contractAccountSet; | |||||
} | |||||
private volatile TransactionSet transactionSet; | |||||
public LedgerAdminDataset getAdminDataset() { | |||||
return ledgerDataset.getAdminDataset(); | |||||
} | |||||
private volatile LedgerDataSet ledgerDataSet; | |||||
public LedgerDataset getLedgerDataset() { | |||||
return ledgerDataset; | |||||
} | |||||
public LedgerState(LedgerBlock block) { | |||||
this.block = block; | |||||
public ContractAccountQuery getContractAccountSet() { | |||||
return ledgerDataset.getContractAccountset(); | |||||
} | |||||
public DataAccountQuery getDataAccountSet() { | |||||
return ledgerDataset.getDataAccountSet(); | |||||
} | |||||
public UserAccountQuery getUserAccountSet() { | |||||
return ledgerDataset.getUserAccountSet(); | |||||
} | |||||
public TransactionSet getTransactionSet() { | |||||
return transactionSet; | |||||
} | } | ||||
} | } |
@@ -0,0 +1,20 @@ | |||||
package com.jd.blockchain.ledger.core; | |||||
import java.util.Set; | |||||
import com.jd.blockchain.utils.Bytes; | |||||
public interface LedgerSecurityManager { | |||||
String DEFAULT_ROLE = "DEFAULT"; | |||||
/** | |||||
* 创建一项与指定的终端用户和节点参与方相关的安全策略; | |||||
* | |||||
* @param endpoints 终端用户的地址列表; | |||||
* @param nodes 节点参与方的地址列表; | |||||
* @return 一项安全策略; | |||||
*/ | |||||
SecurityPolicy createSecurityPolicy(Set<Bytes> endpoints, Set<Bytes> nodes); | |||||
} |
@@ -0,0 +1,396 @@ | |||||
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.ParticipantDataQuery; | |||||
import com.jd.blockchain.ledger.ParticipantDoesNotExistException; | |||||
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.UserDoesNotExistException; | |||||
import com.jd.blockchain.ledger.UserRoles; | |||||
import com.jd.blockchain.ledger.UserRolesSettings; | |||||
import com.jd.blockchain.utils.Bytes; | |||||
/** | |||||
* 账本安全管理器; | |||||
* | |||||
* @author huanghaiquan | |||||
* | |||||
*/ | |||||
public class LedgerSecurityManagerImpl implements LedgerSecurityManager { | |||||
private RolePrivilegeSettings rolePrivilegeSettings; | |||||
private UserRolesSettings userRolesSettings; | |||||
// 用户的权限配置 | |||||
private Map<Bytes, UserRolesPrivileges> userPrivilegesCache = new ConcurrentHashMap<>(); | |||||
private Map<Bytes, UserRoles> userRolesCache = new ConcurrentHashMap<>(); | |||||
private Map<String, RolePrivileges> rolesPrivilegeCache = new ConcurrentHashMap<>(); | |||||
private ParticipantDataQuery participantsQuery; | |||||
private UserAccountQuery userAccountsQuery; | |||||
public LedgerSecurityManagerImpl(RolePrivilegeSettings rolePrivilegeSettings, UserRolesSettings userRolesSettings, | |||||
ParticipantDataQuery participantsQuery, UserAccountQuery userAccountsQuery) { | |||||
this.rolePrivilegeSettings = rolePrivilegeSettings; | |||||
this.userRolesSettings = userRolesSettings; | |||||
this.participantsQuery = participantsQuery; | |||||
this.userAccountsQuery = userAccountsQuery; | |||||
} | |||||
@Override | |||||
public SecurityPolicy createSecurityPolicy(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, participantsQuery, userAccountsQuery); | |||||
} | |||||
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<>(); | |||||
private ParticipantDataQuery participantsQuery; | |||||
private UserAccountQuery userAccountsQuery; | |||||
public UserRolesSecurityPolicy(Map<Bytes, UserRolesPrivileges> endpointPrivilegeMap, | |||||
Map<Bytes, UserRolesPrivileges> nodePrivilegeMap, ParticipantDataQuery participantsQuery, | |||||
UserAccountQuery userAccountsQuery) { | |||||
this.endpointPrivilegeMap = endpointPrivilegeMap; | |||||
this.nodePrivilegeMap = nodePrivilegeMap; | |||||
this.participantsQuery = participantsQuery; | |||||
this.userAccountsQuery = userAccountsQuery; | |||||
} | |||||
@Override | |||||
public boolean isEndpointEnable(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 isEndpointEnable(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 isNodeEnable(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 isNodeEnable(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 checkEndpointPermission(LedgerPermission permission, MultiIDsPolicy midPolicy) | |||||
throws LedgerSecurityException { | |||||
if (!isEndpointEnable(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 checkEndpointPermission(TransactionPermission permission, MultiIDsPolicy midPolicy) | |||||
throws LedgerSecurityException { | |||||
if (!isEndpointEnable(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 checkNodePermission(LedgerPermission permission, MultiIDsPolicy midPolicy) | |||||
throws LedgerSecurityException { | |||||
if (!isNodeEnable(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 checkNodePermission(TransactionPermission permission, MultiIDsPolicy midPolicy) | |||||
throws LedgerSecurityException { | |||||
if (!isNodeEnable(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(); | |||||
} | |||||
@Override | |||||
public boolean isEndpointValid(MultiIDsPolicy midPolicy) { | |||||
if (MultiIDsPolicy.AT_LEAST_ONE == midPolicy) { | |||||
// 至少一个; | |||||
for (Bytes address : getEndpoints()) { | |||||
if (userAccountsQuery.contains(address)) { | |||||
return true; | |||||
} | |||||
} | |||||
return false; | |||||
} else if (MultiIDsPolicy.ALL == midPolicy) { | |||||
// 全部; | |||||
for (Bytes address : getEndpoints()) { | |||||
if (!userAccountsQuery.contains(address)) { | |||||
return false; | |||||
} | |||||
} | |||||
return true; | |||||
} else { | |||||
throw new IllegalArgumentException("Unsupported MultiIdsPolicy[" + midPolicy + "]!"); | |||||
} | |||||
} | |||||
@Override | |||||
public boolean isNodeValid(MultiIDsPolicy midPolicy) { | |||||
if (MultiIDsPolicy.AT_LEAST_ONE == midPolicy) { | |||||
// 至少一个; | |||||
for (Bytes address : getNodes()) { | |||||
if (participantsQuery.contains(address)) { | |||||
return true; | |||||
} | |||||
} | |||||
return false; | |||||
} else if (MultiIDsPolicy.ALL == midPolicy) { | |||||
// 全部; | |||||
for (Bytes address : getNodes()) { | |||||
if (!participantsQuery.contains(address)) { | |||||
return false; | |||||
} | |||||
} | |||||
return true; | |||||
} else { | |||||
throw new IllegalArgumentException("Unsupported MultiIdsPolicy[" + midPolicy + "]!"); | |||||
} | |||||
} | |||||
@Override | |||||
public void checkEndpointValidity(MultiIDsPolicy midPolicy) throws LedgerSecurityException { | |||||
if (MultiIDsPolicy.AT_LEAST_ONE == midPolicy) { | |||||
// 至少一个; | |||||
for (Bytes address : getEndpoints()) { | |||||
if (userAccountsQuery.contains(address)) { | |||||
return; | |||||
} | |||||
} | |||||
throw new UserDoesNotExistException("All endpoint signers were not registered!"); | |||||
} else if (MultiIDsPolicy.ALL == midPolicy) { | |||||
// 全部; | |||||
for (Bytes address : getEndpoints()) { | |||||
if (!userAccountsQuery.contains(address)) { | |||||
throw new UserDoesNotExistException("The endpoint signer[" + address + "] was not registered!"); | |||||
} | |||||
} | |||||
return; | |||||
} else { | |||||
throw new IllegalArgumentException("Unsupported MultiIdsPolicy[" + midPolicy + "]!"); | |||||
} | |||||
} | |||||
@Override | |||||
public void checkNodeValidity(MultiIDsPolicy midPolicy) throws LedgerSecurityException { | |||||
if (MultiIDsPolicy.AT_LEAST_ONE == midPolicy) { | |||||
// 至少一个; | |||||
for (Bytes address : getNodes()) { | |||||
if (participantsQuery.contains(address)) { | |||||
return; | |||||
} | |||||
} | |||||
throw new ParticipantDoesNotExistException("All node signers were not registered as participant!"); | |||||
} else if (MultiIDsPolicy.ALL == midPolicy) { | |||||
// 全部; | |||||
for (Bytes address : getNodes()) { | |||||
if (!participantsQuery.contains(address)) { | |||||
throw new ParticipantDoesNotExistException( | |||||
"The node signer[" + address + "] was not registered as participant!"); | |||||
} | |||||
} | |||||
} else { | |||||
throw new IllegalArgumentException("Unsupported MultiIdsPolicy[" + midPolicy + "]!"); | |||||
} | |||||
} | |||||
} | |||||
} |
@@ -13,11 +13,18 @@ import java.util.List; | |||||
public interface LedgerTransactionContext { | public interface LedgerTransactionContext { | ||||
/** | /** | ||||
* 账本数据; | |||||
* 账本数据集合; | |||||
* | * | ||||
* @return | * @return | ||||
*/ | */ | ||||
LedgerDataSet getDataSet(); | |||||
LedgerDataset getDataset(); | |||||
/** | |||||
* 事务集合; | |||||
* | |||||
* @return | |||||
*/ | |||||
TransactionSet getTransactionSet(); | |||||
/** | /** | ||||
* 交易请求; | * 交易请求; | ||||
@@ -1,4 +1,4 @@ | |||||
package com.jd.blockchain.ledger.core.impl; | |||||
package com.jd.blockchain.ledger.core; | |||||
import com.jd.blockchain.crypto.HashDigest; | import com.jd.blockchain.crypto.HashDigest; | ||||
import com.jd.blockchain.ledger.DigitalSignature; | import com.jd.blockchain.ledger.DigitalSignature; |
@@ -1,4 +1,4 @@ | |||||
package com.jd.blockchain.ledger.core.impl; | |||||
package com.jd.blockchain.ledger.core; | |||||
import java.util.List; | import java.util.List; | ||||
@@ -8,29 +8,19 @@ import com.jd.blockchain.crypto.HashDigest; | |||||
import com.jd.blockchain.ledger.BlockBody; | import com.jd.blockchain.ledger.BlockBody; | ||||
import com.jd.blockchain.ledger.BlockRollbackException; | import com.jd.blockchain.ledger.BlockRollbackException; | ||||
import com.jd.blockchain.ledger.CryptoSetting; | import com.jd.blockchain.ledger.CryptoSetting; | ||||
import com.jd.blockchain.ledger.DigitalSignature; | |||||
import com.jd.blockchain.ledger.IllegalTransactionException; | import com.jd.blockchain.ledger.IllegalTransactionException; | ||||
import com.jd.blockchain.ledger.LedgerBlock; | import com.jd.blockchain.ledger.LedgerBlock; | ||||
import com.jd.blockchain.ledger.LedgerDataSnapshot; | import com.jd.blockchain.ledger.LedgerDataSnapshot; | ||||
import com.jd.blockchain.ledger.LedgerInitSetting; | import com.jd.blockchain.ledger.LedgerInitSetting; | ||||
import com.jd.blockchain.ledger.LedgerSetting; | |||||
import com.jd.blockchain.ledger.LedgerSettings; | |||||
import com.jd.blockchain.ledger.LedgerTransaction; | import com.jd.blockchain.ledger.LedgerTransaction; | ||||
import com.jd.blockchain.ledger.OperationResult; | import com.jd.blockchain.ledger.OperationResult; | ||||
import com.jd.blockchain.ledger.TransactionContent; | |||||
import com.jd.blockchain.ledger.TransactionRequest; | import com.jd.blockchain.ledger.TransactionRequest; | ||||
import com.jd.blockchain.ledger.TransactionRollbackException; | import com.jd.blockchain.ledger.TransactionRollbackException; | ||||
import com.jd.blockchain.ledger.TransactionState; | import com.jd.blockchain.ledger.TransactionState; | ||||
import com.jd.blockchain.ledger.core.LedgerDataSet; | |||||
import com.jd.blockchain.ledger.core.LedgerEditor; | |||||
import com.jd.blockchain.ledger.core.LedgerTransactionContext; | |||||
import com.jd.blockchain.ledger.core.SettingContext; | |||||
import com.jd.blockchain.ledger.core.TransactionSet; | |||||
import com.jd.blockchain.storage.service.ExPolicyKVStorage; | import com.jd.blockchain.storage.service.ExPolicyKVStorage; | ||||
import com.jd.blockchain.storage.service.VersioningKVStorage; | import com.jd.blockchain.storage.service.VersioningKVStorage; | ||||
import com.jd.blockchain.storage.service.utils.BufferedKVStorage; | import com.jd.blockchain.storage.service.utils.BufferedKVStorage; | ||||
import com.jd.blockchain.transaction.SignatureUtils; | |||||
import com.jd.blockchain.transaction.TxBuilder; | |||||
import com.jd.blockchain.transaction.TxRequestBuilder; | |||||
import com.jd.blockchain.utils.Bytes; | import com.jd.blockchain.utils.Bytes; | ||||
import com.jd.blockchain.utils.codec.Base58Utils; | import com.jd.blockchain.utils.codec.Base58Utils; | ||||
@@ -70,10 +60,8 @@ public class LedgerTransactionalEditor implements LedgerEditor { | |||||
private BufferedKVStorage baseStorage; | private BufferedKVStorage baseStorage; | ||||
/** | /** | ||||
* 上一个交易的上下文; | |||||
* 上一个交易产生的账本快照; | |||||
*/ | */ | ||||
// private LedgerTransactionContextImpl previousTxCtx; | |||||
private TxSnapshot previousTxSnapshot; | private TxSnapshot previousTxSnapshot; | ||||
/** | /** | ||||
@@ -81,6 +69,16 @@ public class LedgerTransactionalEditor implements LedgerEditor { | |||||
*/ | */ | ||||
private volatile LedgerTransactionContextImpl currentTxCtx; | private volatile LedgerTransactionContextImpl currentTxCtx; | ||||
/** | |||||
* 最后提交的账本数据集; | |||||
*/ | |||||
private volatile LedgerDataset latestLedgerDataset; | |||||
/** | |||||
* 最后提交的交易集合; | |||||
*/ | |||||
private volatile TransactionSet latestTransactionSet; | |||||
/** | /** | ||||
* @param ledgerHash | * @param ledgerHash | ||||
* @param cryptoSetting | * @param cryptoSetting | ||||
@@ -115,7 +113,7 @@ public class LedgerTransactionalEditor implements LedgerEditor { | |||||
* @param verifyTx 是否校验交易请求;当外部调用者在调用前已经实施了验证时,将次参数设置为 false 能够提升性能; | * @param verifyTx 是否校验交易请求;当外部调用者在调用前已经实施了验证时,将次参数设置为 false 能够提升性能; | ||||
* @return | * @return | ||||
*/ | */ | ||||
public static LedgerTransactionalEditor createEditor(LedgerBlock previousBlock, LedgerSetting ledgerSetting, | |||||
public static LedgerTransactionalEditor createEditor(LedgerBlock previousBlock, LedgerSettings ledgerSetting, | |||||
String ledgerKeyPrefix, ExPolicyKVStorage ledgerExStorage, VersioningKVStorage ledgerVerStorage) { | String ledgerKeyPrefix, ExPolicyKVStorage ledgerExStorage, VersioningKVStorage ledgerVerStorage) { | ||||
// new block; | // new block; | ||||
HashDigest ledgerHash = previousBlock.getLedgerHash(); | HashDigest ledgerHash = previousBlock.getLedgerHash(); | ||||
@@ -160,6 +158,10 @@ public class LedgerTransactionalEditor implements LedgerEditor { | |||||
private void commitTxSnapshot(TxSnapshot snapshot) { | private void commitTxSnapshot(TxSnapshot snapshot) { | ||||
previousTxSnapshot = snapshot; | previousTxSnapshot = snapshot; | ||||
latestLedgerDataset = currentTxCtx.getDataset(); | |||||
latestLedgerDataset.setReadonly(); | |||||
latestTransactionSet = currentTxCtx.getTransactionSet(); | |||||
latestTransactionSet.setReadonly(); | |||||
currentTxCtx = null; | currentTxCtx = null; | ||||
} | } | ||||
@@ -181,13 +183,23 @@ public class LedgerTransactionalEditor implements LedgerEditor { | |||||
return ledgerHash; | return ledgerHash; | ||||
} | } | ||||
@Override | |||||
public LedgerDataset getLedgerDataset() { | |||||
return latestLedgerDataset; | |||||
} | |||||
@Override | |||||
public TransactionSet getTransactionSet() { | |||||
return latestTransactionSet; | |||||
} | |||||
/** | /** | ||||
* 检查当前账本是否是指定交易请求的账本; | * 检查当前账本是否是指定交易请求的账本; | ||||
* | * | ||||
* @param txRequest | * @param txRequest | ||||
* @return | * @return | ||||
*/ | */ | ||||
private boolean isRequestedLedger(TransactionRequest txRequest) { | |||||
private boolean isRequestMatched(TransactionRequest txRequest) { | |||||
HashDigest reqLedgerHash = txRequest.getTransactionContent().getLedgerHash(); | HashDigest reqLedgerHash = txRequest.getTransactionContent().getLedgerHash(); | ||||
if (ledgerHash == reqLedgerHash) { | if (ledgerHash == reqLedgerHash) { | ||||
return true; | return true; | ||||
@@ -198,49 +210,19 @@ public class LedgerTransactionalEditor implements LedgerEditor { | |||||
return ledgerHash.equals(reqLedgerHash); | 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 | @Override | ||||
public synchronized LedgerTransactionContext newTransaction(TransactionRequest txRequest) { | public synchronized LedgerTransactionContext newTransaction(TransactionRequest txRequest) { | ||||
if (SettingContext.txSettings().verifyLedger() && !isRequestedLedger(txRequest)) { | |||||
// if (SettingContext.txSettings().verifyLedger() && !isRequestMatched(txRequest)) { | |||||
if (!isRequestMatched(txRequest)) { | |||||
throw new IllegalTransactionException( | throw new IllegalTransactionException( | ||||
"Transaction request is dispatched to a wrong ledger! --[TxHash=" | "Transaction request is dispatched to a wrong ledger! --[TxHash=" | ||||
+ txRequest.getTransactionContent().getHash() + "]!", | + txRequest.getTransactionContent().getHash() + "]!", | ||||
TransactionState.IGNORED_BY_WRONG_LEDGER); | TransactionState.IGNORED_BY_WRONG_LEDGER); | ||||
} | } | ||||
// TODO: 把验签和创建交易并行化; | |||||
if (SettingContext.txSettings().verifySignature() && !verifyTxContent(txRequest)) { | |||||
// 抛弃哈希和签名校验失败的交易请求; | |||||
throw new IllegalTransactionException( | |||||
"Wrong transaction signature! --[TxHash=" + txRequest.getTransactionContent().getHash() + "]!", | |||||
TransactionState.IGNORED_BY_WRONG_CONTENT_SIGNATURE); | |||||
} | |||||
if (currentTxCtx != null) { | if (currentTxCtx != null) { | ||||
throw new IllegalStateException( | throw new IllegalStateException( | ||||
"Unable to open another new transaction before the current transaction is completed! --[TxHash=" | "Unable to open another new transaction before the current transaction is completed! --[TxHash=" | ||||
@@ -253,7 +235,7 @@ public class LedgerTransactionalEditor implements LedgerEditor { | |||||
// init storage of new transaction; | // init storage of new transaction; | ||||
BufferedKVStorage txBufferedStorage = new BufferedKVStorage(baseStorage, baseStorage, false); | BufferedKVStorage txBufferedStorage = new BufferedKVStorage(baseStorage, baseStorage, false); | ||||
LedgerDataSetImpl txDataset = null; | |||||
LedgerDataset txDataset = null; | |||||
TransactionSet txset = null; | TransactionSet txset = null; | ||||
if (previousTxSnapshot == null) { | if (previousTxSnapshot == null) { | ||||
// load the starting point of the new transaction; | // load the starting point of the new transaction; | ||||
@@ -262,18 +244,18 @@ public class LedgerTransactionalEditor implements LedgerEditor { | |||||
GenesisSnapshot snpht = (GenesisSnapshot) startingPoint; | GenesisSnapshot snpht = (GenesisSnapshot) startingPoint; | ||||
txDataset = LedgerRepositoryImpl.newDataSet(snpht.initSetting, ledgerKeyPrefix, txBufferedStorage, | txDataset = LedgerRepositoryImpl.newDataSet(snpht.initSetting, ledgerKeyPrefix, txBufferedStorage, | ||||
txBufferedStorage); | txBufferedStorage); | ||||
txset = LedgerRepositoryImpl.newTransactionSet(txDataset.getAdminAccount().getSetting(), | |||||
txset = LedgerRepositoryImpl.newTransactionSet(txDataset.getAdminDataset().getSettings(), | |||||
ledgerKeyPrefix, txBufferedStorage, txBufferedStorage); | ledgerKeyPrefix, txBufferedStorage, txBufferedStorage); | ||||
} else if (startingPoint instanceof TxSnapshot) { | } else if (startingPoint instanceof TxSnapshot) { | ||||
// 新的区块; | // 新的区块; | ||||
// TxSnapshot; reload dataset and txset; | // TxSnapshot; reload dataset and txset; | ||||
TxSnapshot snpht = (TxSnapshot) startingPoint; | TxSnapshot snpht = (TxSnapshot) startingPoint; | ||||
// load dataset; | // load dataset; | ||||
txDataset = LedgerRepositoryImpl.loadDataSet(snpht.dataSnapshot, ledgerKeyPrefix, txBufferedStorage, | |||||
txBufferedStorage, false); | |||||
txDataset = LedgerRepositoryImpl.loadDataSet(snpht.dataSnapshot, cryptoSetting, ledgerKeyPrefix, | |||||
txBufferedStorage, txBufferedStorage, false); | |||||
// load txset; | // load txset; | ||||
txset = LedgerRepositoryImpl.loadTransactionSet(snpht.txsetHash, this.cryptoSetting, ledgerKeyPrefix, | |||||
txset = LedgerRepositoryImpl.loadTransactionSet(snpht.txsetHash, cryptoSetting, ledgerKeyPrefix, | |||||
txBufferedStorage, txBufferedStorage, false); | txBufferedStorage, txBufferedStorage, false); | ||||
} else { | } else { | ||||
// Unreachable; | // Unreachable; | ||||
@@ -283,11 +265,11 @@ public class LedgerTransactionalEditor implements LedgerEditor { | |||||
} else { | } else { | ||||
// Reuse previous object to optimize performance; | // Reuse previous object to optimize performance; | ||||
// load dataset; | // load dataset; | ||||
txDataset = LedgerRepositoryImpl.loadDataSet(previousTxSnapshot.dataSnapshot, ledgerKeyPrefix, | |||||
txBufferedStorage, txBufferedStorage, false); | |||||
txDataset = LedgerRepositoryImpl.loadDataSet(previousTxSnapshot.dataSnapshot, cryptoSetting, | |||||
ledgerKeyPrefix, txBufferedStorage, txBufferedStorage, false); | |||||
// load txset; | // load txset; | ||||
txset = LedgerRepositoryImpl.loadTransactionSet(previousTxSnapshot.txsetHash, this.cryptoSetting, | |||||
txset = LedgerRepositoryImpl.loadTransactionSet(previousTxSnapshot.txsetHash, cryptoSetting, | |||||
ledgerKeyPrefix, txBufferedStorage, txBufferedStorage, false); | ledgerKeyPrefix, txBufferedStorage, txBufferedStorage, false); | ||||
} | } | ||||
@@ -476,28 +458,6 @@ public class LedgerTransactionalEditor implements LedgerEditor { | |||||
} | } | ||||
// /** | |||||
// * 账本的数据上下文; | |||||
// * | |||||
// * @author huanghaiquan | |||||
// * | |||||
// */ | |||||
// private static class LedgerDataContext { | |||||
// | |||||
// protected LedgerDataSetImpl dataset; | |||||
// | |||||
// protected TransactionSet txset; | |||||
// | |||||
// protected BufferedKVStorage storage; | |||||
// | |||||
// public LedgerDataContext(LedgerDataSetImpl dataset, TransactionSet txset, BufferedKVStorage storage) { | |||||
// this.dataset = dataset; | |||||
// this.txset = txset; | |||||
// this.storage = storage; | |||||
// } | |||||
// | |||||
// } | |||||
/** | /** | ||||
* 交易的上下文; | * 交易的上下文; | ||||
* | * | ||||
@@ -510,7 +470,7 @@ public class LedgerTransactionalEditor implements LedgerEditor { | |||||
private TransactionRequest txRequest; | private TransactionRequest txRequest; | ||||
private LedgerDataSetImpl dataset; | |||||
private LedgerDataset dataset; | |||||
private TransactionSet txset; | private TransactionSet txset; | ||||
@@ -524,7 +484,7 @@ public class LedgerTransactionalEditor implements LedgerEditor { | |||||
private HashDigest txRootHash; | private HashDigest txRootHash; | ||||
private LedgerTransactionContextImpl(TransactionRequest txRequest, LedgerDataSetImpl dataset, | |||||
private LedgerTransactionContextImpl(TransactionRequest txRequest, LedgerDataset dataset, | |||||
TransactionSet txset, BufferedKVStorage storage, LedgerTransactionalEditor editor) { | TransactionSet txset, BufferedKVStorage storage, LedgerTransactionalEditor editor) { | ||||
this.txRequest = txRequest; | this.txRequest = txRequest; | ||||
this.dataset = dataset; | this.dataset = dataset; | ||||
@@ -534,10 +494,15 @@ public class LedgerTransactionalEditor implements LedgerEditor { | |||||
} | } | ||||
@Override | @Override | ||||
public LedgerDataSet getDataSet() { | |||||
public LedgerDataset getDataset() { | |||||
return dataset; | return dataset; | ||||
} | } | ||||
@Override | |||||
public TransactionSet getTransactionSet() { | |||||
return txset; | |||||
} | |||||
@Override | @Override | ||||
public TransactionRequest getTransactionRequest() { | public TransactionRequest getTransactionRequest() { | ||||
return txRequest; | return txRequest; | ||||
@@ -620,8 +585,8 @@ public class LedgerTransactionalEditor implements LedgerEditor { | |||||
private TransactionStagedSnapshot takeDataSnapshot() { | private TransactionStagedSnapshot takeDataSnapshot() { | ||||
TransactionStagedSnapshot txDataSnapshot = new TransactionStagedSnapshot(); | TransactionStagedSnapshot txDataSnapshot = new TransactionStagedSnapshot(); | ||||
txDataSnapshot.setAdminAccountHash(dataset.getAdminAccount().getHash()); | |||||
txDataSnapshot.setContractAccountSetHash(dataset.getContractAccountSet().getRootHash()); | |||||
txDataSnapshot.setAdminAccountHash(dataset.getAdminDataset().getHash()); | |||||
txDataSnapshot.setContractAccountSetHash(dataset.getContractAccountset().getRootHash()); | |||||
txDataSnapshot.setDataAccountSetHash(dataset.getDataAccountSet().getRootHash()); | txDataSnapshot.setDataAccountSetHash(dataset.getDataAccountSet().getRootHash()); | ||||
txDataSnapshot.setUserAccountSetHash(dataset.getUserAccountSet().getRootHash()); | txDataSnapshot.setUserAccountSetHash(dataset.getUserAccountSet().getRootHash()); | ||||
return txDataSnapshot; | return txDataSnapshot; |
@@ -1,5 +1,6 @@ | |||||
package com.jd.blockchain.ledger.core; | package com.jd.blockchain.ledger.core; | ||||
import com.jd.blockchain.ledger.MerkleProof; | |||||
import com.jd.blockchain.storage.service.VersioningKVEntry; | import com.jd.blockchain.storage.service.VersioningKVEntry; | ||||
public interface MerkleDataEntry { | public interface MerkleDataEntry { | ||||
@@ -3,11 +3,14 @@ package com.jd.blockchain.ledger.core; | |||||
import com.jd.blockchain.crypto.HashDigest; | import com.jd.blockchain.crypto.HashDigest; | ||||
import com.jd.blockchain.ledger.CryptoSetting; | import com.jd.blockchain.ledger.CryptoSetting; | ||||
import com.jd.blockchain.ledger.LedgerException; | import com.jd.blockchain.ledger.LedgerException; | ||||
import com.jd.blockchain.ledger.MerkleDataNode; | |||||
import com.jd.blockchain.ledger.MerkleProof; | |||||
import com.jd.blockchain.storage.service.ExPolicyKVStorage; | import com.jd.blockchain.storage.service.ExPolicyKVStorage; | ||||
import com.jd.blockchain.storage.service.ExPolicyKVStorage.ExPolicy; | import com.jd.blockchain.storage.service.ExPolicyKVStorage.ExPolicy; | ||||
import com.jd.blockchain.storage.service.VersioningKVEntry; | import com.jd.blockchain.storage.service.VersioningKVEntry; | ||||
import com.jd.blockchain.storage.service.VersioningKVStorage; | import com.jd.blockchain.storage.service.VersioningKVStorage; | ||||
import com.jd.blockchain.storage.service.utils.BufferedKVStorage; | import com.jd.blockchain.storage.service.utils.BufferedKVStorage; | ||||
import com.jd.blockchain.storage.service.utils.VersioningKVData; | |||||
import com.jd.blockchain.utils.Bytes; | import com.jd.blockchain.utils.Bytes; | ||||
import com.jd.blockchain.utils.Transactional; | import com.jd.blockchain.utils.Transactional; | ||||
import com.jd.blockchain.utils.io.BytesUtils; | import com.jd.blockchain.utils.io.BytesUtils; | ||||
@@ -62,12 +65,9 @@ public class MerkleDataSet implements Transactional, MerkleProvable { | |||||
/** | /** | ||||
* 创建一个新的 MerkleDataSet; | * 创建一个新的 MerkleDataSet; | ||||
* | * | ||||
* @param setting | |||||
* 密码设置; | |||||
* @param exPolicyStorage | |||||
* 默克尔树的存储; | |||||
* @param versioningStorage | |||||
* 数据的存储; | |||||
* @param setting 密码设置; | |||||
* @param exPolicyStorage 默克尔树的存储; | |||||
* @param versioningStorage 数据的存储; | |||||
*/ | */ | ||||
public MerkleDataSet(CryptoSetting setting, String keyPrefix, ExPolicyKVStorage exPolicyStorage, | public MerkleDataSet(CryptoSetting setting, String keyPrefix, ExPolicyKVStorage exPolicyStorage, | ||||
VersioningKVStorage versioningStorage) { | VersioningKVStorage versioningStorage) { | ||||
@@ -126,6 +126,10 @@ public class MerkleDataSet implements Transactional, MerkleProvable { | |||||
return readonly; | return readonly; | ||||
} | } | ||||
void setReadonly() { | |||||
this.readonly = true; | |||||
} | |||||
public long getDataCount() { | public long getDataCount() { | ||||
return merkleTree.getDataCount(); | return merkleTree.getDataCount(); | ||||
} | } | ||||
@@ -150,8 +154,27 @@ public class MerkleDataSet implements Transactional, MerkleProvable { | |||||
return values; | return values; | ||||
} | } | ||||
public VersioningKVEntry[] getLatestDataEntries(int fromIndex, int count) { | |||||
if (count > LedgerConsts.MAX_LIST_COUNT) { | |||||
throw new IllegalArgumentException("Count exceed the upper limit[" + LedgerConsts.MAX_LIST_COUNT + "]!"); | |||||
} | |||||
if (fromIndex < 0 || (fromIndex + count) > merkleTree.getDataCount()) { | |||||
throw new IllegalArgumentException("Index out of bound!"); | |||||
} | |||||
VersioningKVEntry[] values = new VersioningKVEntry[count]; | |||||
byte[] bytesValue; | |||||
for (int i = 0; i < count; i++) { | |||||
MerkleDataNode dataNode = merkleTree.getData(fromIndex + i); | |||||
Bytes dataKey = encodeDataKey(dataNode.getKey()); | |||||
bytesValue = valueStorage.get(dataKey, dataNode.getVersion()); | |||||
values[i] = new VersioningKVData(dataNode.getKey(), dataNode.getVersion(), bytesValue); | |||||
} | |||||
return values; | |||||
} | |||||
/** | /** | ||||
* get the data at the specific index; | * get the data at the specific index; | ||||
* | |||||
* @param fromIndex | * @param fromIndex | ||||
* @return | * @return | ||||
*/ | */ | ||||
@@ -163,6 +186,7 @@ public class MerkleDataSet implements Transactional, MerkleProvable { | |||||
/** | /** | ||||
* get the key at the specific index; | * get the key at the specific index; | ||||
* | |||||
* @param fromIndex | * @param fromIndex | ||||
* @return | * @return | ||||
*/ | */ | ||||
@@ -171,7 +195,6 @@ public class MerkleDataSet implements Transactional, MerkleProvable { | |||||
return dataNode.getKey().toUTF8String(); | return dataNode.getKey().toUTF8String(); | ||||
} | } | ||||
/** | /** | ||||
* Create or update the value associated the specified key if the version | * Create or update the value associated the specified key if the version | ||||
* checking is passed.<br> | * checking is passed.<br> | ||||
@@ -183,12 +206,9 @@ public class MerkleDataSet implements Transactional, MerkleProvable { | |||||
* If updating is performed, the version of the key increase by 1. <br> | * If updating is performed, the version of the key increase by 1. <br> | ||||
* If creating is performed, the version of the key initialize by 0. <br> | * If creating is performed, the version of the key initialize by 0. <br> | ||||
* | * | ||||
* @param key | |||||
* The key of data; | |||||
* @param value | |||||
* The value of data; | |||||
* @param version | |||||
* The expected latest version of the key. | |||||
* @param key The key of data; | |||||
* @param value The value of data; | |||||
* @param version The expected latest version of the key. | |||||
* @return The new version of the key. <br> | * @return The new version of the key. <br> | ||||
* If the key is new created success, then return 0; <br> | * If the key is new created success, then return 0; <br> | ||||
* If the key is updated success, then return the new version;<br> | * If the key is updated success, then return the new version;<br> | ||||
@@ -210,12 +230,9 @@ public class MerkleDataSet implements Transactional, MerkleProvable { | |||||
* If updating is performed, the version of the key increase by 1. <br> | * If updating is performed, the version of the key increase by 1. <br> | ||||
* If creating is performed, the version of the key initialize by 0. <br> | * If creating is performed, the version of the key initialize by 0. <br> | ||||
* | * | ||||
* @param key | |||||
* The key of data; | |||||
* @param value | |||||
* The value of data; | |||||
* @param version | |||||
* The expected latest version of the key. | |||||
* @param key The key of data; | |||||
* @param value The value of data; | |||||
* @param version The expected latest version of the key. | |||||
* @return The new version of the key. <br> | * @return The new version of the key. <br> | ||||
* If the key is new created success, then return 0; <br> | * If the key is new created success, then return 0; <br> | ||||
* If the key is updated success, then return the new version;<br> | * If the key is updated success, then return the new version;<br> | ||||
@@ -404,12 +421,22 @@ public class MerkleDataSet implements Transactional, MerkleProvable { | |||||
return getDataEntry(Bytes.fromString(key)); | return getDataEntry(Bytes.fromString(key)); | ||||
} | } | ||||
/** | |||||
* | |||||
* @param key | |||||
* @return Null if the key doesn't exist! | |||||
*/ | |||||
public VersioningKVEntry getDataEntry(Bytes key) { | public VersioningKVEntry getDataEntry(Bytes key) { | ||||
long latestVersion = getMerkleVersion(key); | long latestVersion = getMerkleVersion(key); | ||||
if (latestVersion < 0) { | if (latestVersion < 0) { | ||||
return null; | return null; | ||||
} | } | ||||
return valueStorage.getEntry(key, latestVersion); | |||||
Bytes dataKey = encodeDataKey(key); | |||||
byte[] value = valueStorage.get(dataKey, latestVersion); | |||||
if (value == null) { | |||||
return null; | |||||
} | |||||
return new VersioningKVData(key, latestVersion, value); | |||||
} | } | ||||
public VersioningKVEntry getDataEntry(Bytes key, long version) { | public VersioningKVEntry getDataEntry(Bytes key, long version) { | ||||
@@ -420,7 +447,12 @@ public class MerkleDataSet implements Transactional, MerkleProvable { | |||||
return null; | return null; | ||||
} | } | ||||
version = version < 0 ? latestVersion : version; | version = version < 0 ? latestVersion : version; | ||||
return valueStorage.getEntry(key, version); | |||||
Bytes dataKey = encodeDataKey(key); | |||||
byte[] value = valueStorage.get(dataKey, version); | |||||
if (value == null) { | |||||
return null; | |||||
} | |||||
return new VersioningKVData(key, version, value); | |||||
} | } | ||||
public MerkleDataEntry getMerkleEntry(Bytes key, long version) { | public MerkleDataEntry getMerkleEntry(Bytes key, long version) { | ||||
@@ -1,6 +1,7 @@ | |||||
package com.jd.blockchain.ledger.core; | package com.jd.blockchain.ledger.core; | ||||
import com.jd.blockchain.crypto.HashDigest; | import com.jd.blockchain.crypto.HashDigest; | ||||
import com.jd.blockchain.ledger.MerkleProof; | |||||
import com.jd.blockchain.utils.Bytes; | import com.jd.blockchain.utils.Bytes; | ||||
public interface MerkleProvable { | public interface MerkleProvable { | ||||
@@ -20,6 +20,9 @@ import com.jd.blockchain.crypto.HashDigest; | |||||
import com.jd.blockchain.crypto.HashFunction; | import com.jd.blockchain.crypto.HashFunction; | ||||
import com.jd.blockchain.ledger.CryptoSetting; | import com.jd.blockchain.ledger.CryptoSetting; | ||||
import com.jd.blockchain.ledger.LedgerException; | import com.jd.blockchain.ledger.LedgerException; | ||||
import com.jd.blockchain.ledger.MerkleDataNode; | |||||
import com.jd.blockchain.ledger.MerkleNode; | |||||
import com.jd.blockchain.ledger.MerkleProof; | |||||
import com.jd.blockchain.storage.service.ExPolicyKVStorage; | import com.jd.blockchain.storage.service.ExPolicyKVStorage; | ||||
import com.jd.blockchain.storage.service.ExPolicyKVStorage.ExPolicy; | import com.jd.blockchain.storage.service.ExPolicyKVStorage.ExPolicy; | ||||
import com.jd.blockchain.utils.Bytes; | import com.jd.blockchain.utils.Bytes; | ||||
@@ -0,0 +1,21 @@ | |||||
package com.jd.blockchain.ledger.core; | |||||
/** | |||||
* 多重身份的校验策略; | |||||
* | |||||
* @author huanghaiquan | |||||
* | |||||
*/ | |||||
public enum MultiIDsPolicy { | |||||
/** | |||||
* 至少有一个都能通过; | |||||
*/ | |||||
AT_LEAST_ONE, | |||||
/** | |||||
* 每一个都能通过; | |||||
*/ | |||||
ALL | |||||
} |
@@ -1,8 +1,7 @@ | |||||
package com.jd.blockchain.ledger.core.impl; | |||||
package com.jd.blockchain.ledger.core; | |||||
import com.jd.blockchain.crypto.PubKey; | import com.jd.blockchain.crypto.PubKey; | ||||
import com.jd.blockchain.ledger.AccountHeader; | import com.jd.blockchain.ledger.AccountHeader; | ||||
import com.jd.blockchain.ledger.core.AccountAccessPolicy; | |||||
import com.jd.blockchain.utils.Bytes; | import com.jd.blockchain.utils.Bytes; | ||||
/** | /** |
@@ -2,8 +2,6 @@ package com.jd.blockchain.ledger.core; | |||||
import com.jd.blockchain.ledger.BytesValue; | import com.jd.blockchain.ledger.BytesValue; | ||||
import com.jd.blockchain.ledger.Operation; | import com.jd.blockchain.ledger.Operation; | ||||
import com.jd.blockchain.ledger.core.impl.OperationHandleContext; | |||||
public interface OperationHandle { | public interface OperationHandle { | ||||
@@ -13,42 +11,22 @@ public interface OperationHandle { | |||||
* @param operationType | * @param operationType | ||||
* @return | * @return | ||||
*/ | */ | ||||
boolean support(Class<?> operationType); | |||||
Class<?> getOperationType(); | |||||
/** | /** | ||||
* 同步解析和执行操作; | * 同步解析和执行操作; | ||||
* | * | ||||
* | * | ||||
* @param op | |||||
* 操作实例; | |||||
* @param newBlockDataset | |||||
* 需要修改的新区块的数据集; | |||||
* @param requestContext | |||||
* 交易请求上下文; | |||||
* @param previousBlockDataset | |||||
* 新区块的前一个区块的数据集;即未提交新区块之前的经过共识的账本最新数据集; | |||||
* @param op 操作实例; | |||||
* @param newBlockDataset 需要修改的新区块的数据集; | |||||
* @param requestContext 交易请求上下文; | |||||
* @param previousBlockDataset 新区块的前一个区块的数据集;即未提交新区块之前的经过共识的账本最新数据集;注:此数据集是只读的; | |||||
* | * | ||||
* @return 操作执行结果 | |||||
* @param handleContext 操作上下文;` | |||||
* @param ledgerService | |||||
* @return | |||||
*/ | */ | ||||
BytesValue process(Operation op, LedgerDataSet newBlockDataset, TransactionRequestContext requestContext, | |||||
LedgerDataSet previousBlockDataset, OperationHandleContext handleContext, LedgerService ledgerService); | |||||
BytesValue process(Operation op, LedgerDataset newBlockDataset, TransactionRequestExtension requestContext, | |||||
LedgerDataQuery 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); | |||||
} | } |
@@ -0,0 +1,15 @@ | |||||
package com.jd.blockchain.ledger.core; | |||||
import com.jd.blockchain.ledger.Operation; | |||||
/** | |||||
* 在交易处理过程中,提供对多种交易操作处理器互相调用的机制; | |||||
* | |||||
* @author huanghaiquan | |||||
* | |||||
*/ | |||||
public interface OperationHandleContext { | |||||
void handle(Operation operation); | |||||
} |
@@ -0,0 +1,9 @@ | |||||
package com.jd.blockchain.ledger.core; | |||||
import com.jd.blockchain.ledger.Operation; | |||||
public interface OperationHandleRegisteration { | |||||
OperationHandle getHandle(Class<? extends Operation> operationType); | |||||
} |
@@ -1,21 +0,0 @@ | |||||
package com.jd.blockchain.ledger.core; | |||||
/** | |||||
* @author hhq | |||||
* @version 1.0 | |||||
* @created 14-6��-2018 12:13:33 | |||||
*/ | |||||
public class P2PRealm { | |||||
public Peer m_Peer; | |||||
public P2PRealm(){ | |||||
} | |||||
public void finalize() throws Throwable { | |||||
} | |||||
} |
@@ -2,6 +2,7 @@ package com.jd.blockchain.ledger.core; | |||||
import com.jd.blockchain.crypto.PubKey; | import com.jd.blockchain.crypto.PubKey; | ||||
import com.jd.blockchain.ledger.ParticipantNode; | import com.jd.blockchain.ledger.ParticipantNode; | ||||
import com.jd.blockchain.utils.Bytes; | |||||
import com.jd.blockchain.ledger.ParticipantNodeState; | import com.jd.blockchain.ledger.ParticipantNodeState; | ||||
/** | /** | ||||
@@ -13,7 +14,7 @@ import com.jd.blockchain.ledger.ParticipantNodeState; | |||||
public class ParticipantCertData implements ParticipantNode { | public class ParticipantCertData implements ParticipantNode { | ||||
private int id; | private int id; | ||||
private String address; | |||||
private Bytes address; | |||||
private String name; | private String name; | ||||
private PubKey pubKey; | private PubKey pubKey; | ||||
private ParticipantNodeState participantNodeState; | private ParticipantNodeState participantNodeState; | ||||
@@ -29,14 +30,14 @@ public class ParticipantCertData implements ParticipantNode { | |||||
this.participantNodeState = participantNode.getParticipantNodeState(); | this.participantNodeState = participantNode.getParticipantNodeState(); | ||||
} | } | ||||
public ParticipantCertData(String address, String name, PubKey pubKey) { | |||||
public ParticipantCertData(Bytes address, String name, PubKey pubKey) { | |||||
this.address = address; | this.address = address; | ||||
this.name = name; | this.name = name; | ||||
this.pubKey = pubKey; | this.pubKey = pubKey; | ||||
} | } | ||||
@Override | @Override | ||||
public String getAddress() { | |||||
public Bytes getAddress() { | |||||
return address; | return address; | ||||
} | } | ||||
@@ -4,14 +4,16 @@ import com.jd.blockchain.binaryproto.BinaryProtocol; | |||||
import com.jd.blockchain.binaryproto.DataContractRegistry; | import com.jd.blockchain.binaryproto.DataContractRegistry; | ||||
import com.jd.blockchain.crypto.HashDigest; | import com.jd.blockchain.crypto.HashDigest; | ||||
import com.jd.blockchain.ledger.ParticipantNode; | import com.jd.blockchain.ledger.ParticipantNode; | ||||
import com.jd.blockchain.ledger.ParticipantDataQuery; | |||||
import com.jd.blockchain.ledger.CryptoSetting; | import com.jd.blockchain.ledger.CryptoSetting; | ||||
import com.jd.blockchain.ledger.LedgerException; | import com.jd.blockchain.ledger.LedgerException; | ||||
import com.jd.blockchain.ledger.MerkleProof; | |||||
import com.jd.blockchain.storage.service.ExPolicyKVStorage; | import com.jd.blockchain.storage.service.ExPolicyKVStorage; | ||||
import com.jd.blockchain.storage.service.VersioningKVStorage; | import com.jd.blockchain.storage.service.VersioningKVStorage; | ||||
import com.jd.blockchain.utils.Bytes; | import com.jd.blockchain.utils.Bytes; | ||||
import com.jd.blockchain.utils.Transactional; | import com.jd.blockchain.utils.Transactional; | ||||
public class ParticipantDataSet implements Transactional, MerkleProvable { | |||||
public class ParticipantDataset implements Transactional, MerkleProvable, ParticipantDataQuery { | |||||
static { | static { | ||||
DataContractRegistry.register(ParticipantNode.class); | DataContractRegistry.register(ParticipantNode.class); | ||||
@@ -19,12 +21,12 @@ public class ParticipantDataSet implements Transactional, MerkleProvable { | |||||
private MerkleDataSet dataset; | private MerkleDataSet dataset; | ||||
public ParticipantDataSet(CryptoSetting cryptoSetting, String prefix, ExPolicyKVStorage exPolicyStorage, | |||||
public ParticipantDataset(CryptoSetting cryptoSetting, String prefix, ExPolicyKVStorage exPolicyStorage, | |||||
VersioningKVStorage verStorage) { | VersioningKVStorage verStorage) { | ||||
dataset = new MerkleDataSet(cryptoSetting, prefix, exPolicyStorage, verStorage); | dataset = new MerkleDataSet(cryptoSetting, prefix, exPolicyStorage, verStorage); | ||||
} | } | ||||
public ParticipantDataSet(HashDigest merkleRootHash, CryptoSetting cryptoSetting, String prefix, | |||||
public ParticipantDataset(HashDigest merkleRootHash, CryptoSetting cryptoSetting, String prefix, | |||||
ExPolicyKVStorage exPolicyStorage, VersioningKVStorage verStorage, boolean readonly) { | ExPolicyKVStorage exPolicyStorage, VersioningKVStorage verStorage, boolean readonly) { | ||||
dataset = new MerkleDataSet(merkleRootHash, cryptoSetting, prefix, exPolicyStorage, verStorage, readonly); | dataset = new MerkleDataSet(merkleRootHash, cryptoSetting, prefix, exPolicyStorage, verStorage, readonly); | ||||
} | } | ||||
@@ -54,6 +56,7 @@ public class ParticipantDataSet implements Transactional, MerkleProvable { | |||||
dataset.cancel(); | dataset.cancel(); | ||||
} | } | ||||
@Override | |||||
public long getParticipantCount() { | public long getParticipantCount() { | ||||
return dataset.getDataCount(); | return dataset.getDataCount(); | ||||
} | } | ||||
@@ -92,9 +95,15 @@ public class ParticipantDataSet implements Transactional, MerkleProvable { | |||||
} | } | ||||
} | } | ||||
private Bytes encodeKey(String address) { | |||||
// return id + ""; | |||||
return Bytes.fromString(address); | |||||
private Bytes encodeKey(Bytes address) { | |||||
return address; | |||||
} | |||||
@Override | |||||
public boolean contains(Bytes address) { | |||||
Bytes key = encodeKey(address); | |||||
long latestVersion = dataset.getVersion(key); | |||||
return latestVersion > -1; | |||||
} | } | ||||
/** | /** | ||||
@@ -106,7 +115,8 @@ public class ParticipantDataSet implements Transactional, MerkleProvable { | |||||
* @param address | * @param address | ||||
* @return | * @return | ||||
*/ | */ | ||||
public ParticipantNode getParticipant(String address) { | |||||
@Override | |||||
public ParticipantNode getParticipant(Bytes address) { | |||||
Bytes key = encodeKey(address); | Bytes key = encodeKey(address); | ||||
byte[] bytes = dataset.getValue(key); | byte[] bytes = dataset.getValue(key); | ||||
if (bytes == null) { | if (bytes == null) { | ||||
@@ -114,11 +124,12 @@ public class ParticipantDataSet implements Transactional, MerkleProvable { | |||||
} | } | ||||
return BinaryProtocol.decode(bytes); | return BinaryProtocol.decode(bytes); | ||||
} | } | ||||
@Override | |||||
public ParticipantNode[] getParticipants() { | public ParticipantNode[] getParticipants() { | ||||
byte[][] bytes = dataset.getLatestValues(0, (int)dataset.getDataCount()); | |||||
byte[][] bytes = dataset.getLatestValues(0, (int) dataset.getDataCount()); | |||||
ParticipantNode[] pns = new ParticipantNode[bytes.length]; | ParticipantNode[] pns = new ParticipantNode[bytes.length]; | ||||
for (int i = 0; i < pns.length; i++) { | for (int i = 0; i < pns.length; i++) { | ||||
pns[i] = BinaryProtocol.decode(bytes[i]); | pns[i] = BinaryProtocol.decode(bytes[i]); | ||||
} | } |
@@ -1,7 +1,5 @@ | |||||
package com.jd.blockchain.ledger.core; | package com.jd.blockchain.ledger.core; | ||||
import java.util.SortedSet; | |||||
public interface PermissionService { | public interface PermissionService { | ||||
boolean checkLedgerPermission(); | boolean checkLedgerPermission(); | ||||
@@ -1,21 +0,0 @@ | |||||
//package com.jd.blockchain.ledger.core; | |||||
// | |||||
//import com.jd.blockchain.crypto.hash.HashDigest; | |||||
//import com.jd.blockchain.ledger.data.DigitalSignatureBlob; | |||||
// | |||||
//import my.utils.io.ExistentialKVStorage; | |||||
//import my.utils.io.VersioningKVStorage; | |||||
// | |||||
//public class PrivilegeDataSet extends GenericMerkleDataSet<Authorization, AuthorizationVO> { | |||||
// | |||||
// public PrivilegeDataSet(CryptoSetting setting, ExistentialKVStorage merkleTreeStorage, VersioningKVStorage dataStorage) { | |||||
// this(null, setting, merkleTreeStorage, dataStorage, false); | |||||
// } | |||||
// | |||||
// public PrivilegeDataSet(HashDigest rootHash, CryptoSetting setting, ExistentialKVStorage merkleTreeStorage, | |||||
// VersioningKVStorage dataStorage, boolean readonly) { | |||||
// super(rootHash, setting, merkleTreeStorage, dataStorage, readonly, Authorization.class, AuthorizationVO.class, | |||||
// DigitalSignatureBlob.class); | |||||
// } | |||||
// | |||||
//} |
@@ -0,0 +1,293 @@ | |||||
package com.jd.blockchain.ledger.core; | |||||
import com.jd.blockchain.binaryproto.BinaryProtocol; | |||||
import com.jd.blockchain.crypto.HashDigest; | |||||
import com.jd.blockchain.ledger.CryptoSetting; | |||||
import com.jd.blockchain.ledger.LedgerException; | |||||
import com.jd.blockchain.ledger.LedgerPermission; | |||||
import com.jd.blockchain.ledger.LedgerPrivilege; | |||||
import com.jd.blockchain.ledger.MerkleProof; | |||||
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; | |||||
import com.jd.blockchain.ledger.TransactionPrivilege; | |||||
import com.jd.blockchain.storage.service.ExPolicyKVStorage; | |||||
import com.jd.blockchain.storage.service.VersioningKVEntry; | |||||
import com.jd.blockchain.storage.service.VersioningKVStorage; | |||||
import com.jd.blockchain.utils.Bytes; | |||||
import com.jd.blockchain.utils.Transactional; | |||||
public class RolePrivilegeDataset implements Transactional, MerkleProvable, RolePrivilegeSettings { | |||||
private MerkleDataSet dataset; | |||||
public RolePrivilegeDataset(CryptoSetting cryptoSetting, String prefix, ExPolicyKVStorage exPolicyStorage, | |||||
VersioningKVStorage verStorage) { | |||||
dataset = new MerkleDataSet(cryptoSetting, prefix, exPolicyStorage, verStorage); | |||||
} | |||||
public RolePrivilegeDataset(HashDigest merkleRootHash, CryptoSetting cryptoSetting, String prefix, | |||||
ExPolicyKVStorage exPolicyStorage, VersioningKVStorage verStorage, boolean readonly) { | |||||
dataset = new MerkleDataSet(merkleRootHash, cryptoSetting, prefix, exPolicyStorage, verStorage, readonly); | |||||
} | |||||
@Override | |||||
public HashDigest getRootHash() { | |||||
return dataset.getRootHash(); | |||||
} | |||||
@Override | |||||
public MerkleProof getProof(Bytes key) { | |||||
return dataset.getProof(key); | |||||
} | |||||
@Override | |||||
public boolean isUpdated() { | |||||
return dataset.isUpdated(); | |||||
} | |||||
@Override | |||||
public void commit() { | |||||
dataset.commit(); | |||||
} | |||||
@Override | |||||
public void cancel() { | |||||
dataset.cancel(); | |||||
} | |||||
@Override | |||||
public long getRoleCount() { | |||||
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); | |||||
long nv = setRolePrivilege(roleAuth); | |||||
if (nv < 0) { | |||||
throw new LedgerException("Role[" + roleName + "] already exist!"); | |||||
} | |||||
return nv; | |||||
} | |||||
@Override | |||||
public long addRolePrivilege(String roleName, LedgerPermission[] ledgerPermissions, | |||||
TransactionPermission[] txPermissions) { | |||||
LedgerPrivilege ledgerPrivilege = new LedgerPrivilege(); | |||||
for (LedgerPermission lp : ledgerPermissions) { | |||||
ledgerPrivilege.enable(lp); | |||||
} | |||||
TransactionPrivilege txPrivilege = new TransactionPrivilege(); | |||||
for (TransactionPermission tp : txPermissions) { | |||||
txPrivilege.enable(tp); | |||||
} | |||||
return addRolePrivilege(roleName, ledgerPrivilege, txPrivilege); | |||||
} | |||||
/** | |||||
* 设置角色权限; <br> | |||||
* 如果版本校验不匹配,则返回 -1; | |||||
* | |||||
* @param roleAuth | |||||
* @return | |||||
*/ | |||||
private long setRolePrivilege(RolePrivileges roleAuth) { | |||||
if (roleAuth.getRoleName().length() > MAX_ROLE_NAME_LENGTH) { | |||||
throw new LedgerException("Too long role name!"); | |||||
} | |||||
Bytes key = encodeKey(roleAuth.getRoleName()); | |||||
byte[] privilegeBytes = BinaryProtocol.encode(roleAuth, PrivilegeSet.class); | |||||
return dataset.setValue(key, privilegeBytes, roleAuth.getVersion()); | |||||
} | |||||
/** | |||||
* 更新角色权限; <br> | |||||
* 如果指定的角色不存在,或者版本不匹配,则引发 {@link LedgerException} 异常; | |||||
* | |||||
* @param participant | |||||
*/ | |||||
@Override | |||||
public void updateRolePrivilege(RolePrivileges roleAuth) { | |||||
long nv = setRolePrivilege(roleAuth); | |||||
if (nv < 0) { | |||||
throw new LedgerException("Update to RoleAuthorization[" + roleAuth.getRoleName() | |||||
+ "] failed due to wrong version[" + roleAuth.getVersion() + "] !"); | |||||
} | |||||
} | |||||
/** | |||||
* 授权角色指定的权限; <br> | |||||
* 如果角色不存在,则返回 -1; | |||||
* | |||||
* @param roleName 角色; | |||||
* @param permissions 权限列表; | |||||
* @return | |||||
*/ | |||||
@Override | |||||
public long enablePermissions(String roleName, LedgerPermission... permissions) { | |||||
RolePrivileges roleAuth = getRolePrivilege(roleName); | |||||
if (roleAuth == null) { | |||||
return -1; | |||||
} | |||||
roleAuth.getLedgerPrivilege().enable(permissions); | |||||
return setRolePrivilege(roleAuth); | |||||
} | |||||
/** | |||||
* 授权角色指定的权限; <br> | |||||
* 如果角色不存在,则返回 -1; | |||||
* | |||||
* @param roleName 角色; | |||||
* @param permissions 权限列表; | |||||
* @return | |||||
*/ | |||||
@Override | |||||
public long enablePermissions(String roleName, TransactionPermission... permissions) { | |||||
RolePrivileges roleAuth = getRolePrivilege(roleName); | |||||
if (roleAuth == null) { | |||||
return -1; | |||||
} | |||||
roleAuth.getTransactionPrivilege().enable(permissions); | |||||
return setRolePrivilege(roleAuth); | |||||
} | |||||
/** | |||||
* 禁止角色指定的权限; <br> | |||||
* 如果角色不存在,则返回 -1; | |||||
* | |||||
* @param roleName 角色; | |||||
* @param permissions 权限列表; | |||||
* @return | |||||
*/ | |||||
@Override | |||||
public long disablePermissions(String roleName, LedgerPermission... permissions) { | |||||
RolePrivileges roleAuth = getRolePrivilege(roleName); | |||||
if (roleAuth == null) { | |||||
return -1; | |||||
} | |||||
roleAuth.getLedgerPrivilege().disable(permissions); | |||||
return setRolePrivilege(roleAuth); | |||||
} | |||||
/** | |||||
* 禁止角色指定的权限; <br> | |||||
* 如果角色不存在,则返回 -1; | |||||
* | |||||
* @param roleName 角色; | |||||
* @param permissions 权限列表; | |||||
* @return | |||||
*/ | |||||
@Override | |||||
public long disablePermissions(String roleName, TransactionPermission... permissions) { | |||||
RolePrivileges roleAuth = getRolePrivilege(roleName); | |||||
if (roleAuth == null) { | |||||
return -1; | |||||
} | |||||
roleAuth.getTransactionPrivilege().disable(permissions); | |||||
return setRolePrivilege(roleAuth); | |||||
} | |||||
/** | |||||
* 授权角色指定的权限; <br> | |||||
* 如果角色不存在,则返回 -1; | |||||
* | |||||
* @param roleName | |||||
* @param ledgerPermissions | |||||
* @param txPermissions | |||||
* @return | |||||
*/ | |||||
@Override | |||||
public long enablePermissions(String roleName, LedgerPermission[] ledgerPermissions, | |||||
TransactionPermission[] txPermissions) { | |||||
RolePrivileges roleAuth = getRolePrivilege(roleName); | |||||
if (roleAuth == null) { | |||||
return -1; | |||||
} | |||||
roleAuth.getLedgerPrivilege().enable(ledgerPermissions); | |||||
roleAuth.getTransactionPrivilege().enable(txPermissions); | |||||
return setRolePrivilege(roleAuth); | |||||
} | |||||
/** | |||||
* 禁用角色指定的权限; <br> | |||||
* 如果角色不存在,则返回 -1; | |||||
* | |||||
* @param roleName | |||||
* @param ledgerPermissions | |||||
* @param txPermissions | |||||
* @return | |||||
*/ | |||||
@Override | |||||
public long disablePermissions(String roleName, LedgerPermission[] ledgerPermissions, | |||||
TransactionPermission[] txPermissions) { | |||||
RolePrivileges roleAuth = getRolePrivilege(roleName); | |||||
if (roleAuth == null) { | |||||
return -1; | |||||
} | |||||
roleAuth.getLedgerPrivilege().disable(ledgerPermissions); | |||||
roleAuth.getTransactionPrivilege().disable(txPermissions); | |||||
return setRolePrivilege(roleAuth); | |||||
} | |||||
private Bytes encodeKey(String address) { | |||||
// return id + ""; | |||||
return Bytes.fromString(address); | |||||
} | |||||
/** | |||||
* 查询角色权限; | |||||
* | |||||
* <br> | |||||
* 如果不存在,则返回 null; | |||||
* | |||||
* @param address | |||||
* @return | |||||
*/ | |||||
@Override | |||||
public RolePrivileges getRolePrivilege(String roleName) { | |||||
// 只返回最新版本; | |||||
Bytes key = encodeKey(roleName); | |||||
VersioningKVEntry kv = dataset.getDataEntry(key); | |||||
if (kv == null) { | |||||
return null; | |||||
} | |||||
PrivilegeSet privilege = BinaryProtocol.decode(kv.getValue()); | |||||
return new RolePrivileges(roleName, kv.getVersion(), privilege); | |||||
} | |||||
@Override | |||||
public RolePrivileges[] getRolePrivileges(int index, int count) { | |||||
VersioningKVEntry[] kvEntries = dataset.getLatestDataEntries(index, count); | |||||
RolePrivileges[] pns = new RolePrivileges[kvEntries.length]; | |||||
PrivilegeSet privilege; | |||||
for (int i = 0; i < pns.length; i++) { | |||||
privilege = BinaryProtocol.decode(kvEntries[i].getValue()); | |||||
pns[i] = new RolePrivileges(kvEntries[i].getKey().toUTF8String(), kvEntries[i].getVersion(), privilege); | |||||
} | |||||
return pns; | |||||
} | |||||
@Override | |||||
public RolePrivileges[] getRolePrivileges() { | |||||
return getRolePrivileges(0, (int) getRoleCount()); | |||||
} | |||||
@Override | |||||
public boolean isReadonly() { | |||||
return dataset.isReadonly(); | |||||
} | |||||
@Override | |||||
public boolean contains(String roleName) { | |||||
Bytes key = encodeKey(roleName); | |||||
return dataset.getVersion(key) > -1; | |||||
} | |||||
} |
@@ -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) { | |||||
} | |||||
} |
@@ -0,0 +1,142 @@ | |||||
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(); | |||||
/** | |||||
* 终端身份是否合法; | |||||
* | |||||
* @param midPolicy | |||||
* @return | |||||
*/ | |||||
boolean isEndpointValid(MultiIDsPolicy midPolicy); | |||||
/** | |||||
* 节点身份是否合法; | |||||
* | |||||
* @param midPolicy | |||||
* @return | |||||
*/ | |||||
boolean isNodeValid(MultiIDsPolicy midPolicy); | |||||
/** | |||||
* 检查签署交易的终端用户(来自{@link TransactionRequest#getEndpointSignatures()})是否被授权了参数指定的权限;<br> | |||||
* | |||||
* @param permission 要检查的权限; | |||||
* @param midPolicy 针对多个签名用户的权限策略; | |||||
* @return 返回 true 表示获得授权; 返回 false 表示未获得授权; | |||||
*/ | |||||
boolean isEndpointEnable(LedgerPermission permission, MultiIDsPolicy midPolicy); | |||||
/** | |||||
* 检查签署交易的终端用户(来自{@link TransactionRequest#getEndpointSignatures()})是否被授权了参数指定的权限;<br> | |||||
* | |||||
* @param permission 要检查的权限; | |||||
* @param midPolicy 针对多个签名用户的权限策略; | |||||
* @return 返回 true 表示获得授权; 返回 false 表示未获得授权; | |||||
*/ | |||||
boolean isEndpointEnable(TransactionPermission permission, MultiIDsPolicy midPolicy); | |||||
/** | |||||
* 检查签署交易的节点参与方(来自{@link TransactionRequest#getNodeSignatures()})是否被授权了参数指定的权限;<br> | |||||
* | |||||
* @param permission 要检查的权限; | |||||
* @param midPolicy 针对多个签名用户的权限策略; | |||||
* @return 返回 true 表示获得授权; 返回 false 表示未获得授权; | |||||
*/ | |||||
boolean isNodeEnable(LedgerPermission permission, MultiIDsPolicy midPolicy); | |||||
/** | |||||
* 检查签署交易的节点参与方(来自{@link TransactionRequest#getNodeSignatures()})是否被授权了参数指定的权限;<br> | |||||
* | |||||
* @param permission 要检查的权限; | |||||
* @param midPolicy 针对多个签名用户的权限策略; | |||||
* @return 返回 true 表示获得授权; 返回 false 表示未获得授权; | |||||
*/ | |||||
boolean isNodeEnable(TransactionPermission permission, MultiIDsPolicy midPolicy); | |||||
/** | |||||
* 检查终端身份的合法性; | |||||
* | |||||
* @param midPolicy | |||||
* @throws LedgerSecurityException | |||||
*/ | |||||
void checkEndpointValidity(MultiIDsPolicy midPolicy) throws LedgerSecurityException; | |||||
/** | |||||
* 检查节点身份的合法性; | |||||
* | |||||
* @param midPolicy | |||||
* @throws LedgerSecurityException | |||||
*/ | |||||
void checkNodeValidity(MultiIDsPolicy midPolicy) throws LedgerSecurityException; | |||||
/** | |||||
* 检查签署交易的终端用户(来自{@link TransactionRequest#getEndpointSignatures()})是否被授权了参数指定的权限;<br> | |||||
* 如果未获授权,方法将引发 {@link LedgerSecurityException} 异常; | |||||
* | |||||
* @param permission 要检查的权限; | |||||
* @param midPolicy 针对多个签名用户的权限策略; | |||||
* @throws LedgerSecurityException | |||||
*/ | |||||
void checkEndpointPermission(LedgerPermission permission, MultiIDsPolicy midPolicy) throws LedgerSecurityException; | |||||
/** | |||||
* 检查签署交易的终端用户(来自{@link TransactionRequest#getEndpointSignatures()})是否被授权了参数指定的权限;<br> | |||||
* 如果未获授权,方法将引发 {@link LedgerSecurityException} 异常; | |||||
* | |||||
* @param permission | |||||
* @param midPolicy | |||||
* @throws LedgerSecurityException | |||||
*/ | |||||
void checkEndpointPermission(TransactionPermission permission, MultiIDsPolicy midPolicy) | |||||
throws LedgerSecurityException; | |||||
/** | |||||
* 检查签署交易的节点参与方(来自{@link TransactionRequest#getNodeSignatures()})是否被授权了参数指定的权限;<br> | |||||
* 如果未获授权,方法将引发 {@link LedgerSecurityException} 异常; | |||||
* | |||||
* @param permission | |||||
* @param midPolicy | |||||
* @throws LedgerSecurityException | |||||
*/ | |||||
void checkNodePermission(LedgerPermission permission, MultiIDsPolicy midPolicy) throws LedgerSecurityException; | |||||
/** | |||||
* 检查签署交易的节点参与方(来自{@link TransactionRequest#getNodeSignatures()})是否被授权了参数指定的权限;<br> | |||||
* 如果未获授权,方法将引发 {@link LedgerSecurityException} 异常; | |||||
* | |||||
* @param permission | |||||
* @param midPolicy | |||||
* @throws LedgerSecurityException | |||||
*/ | |||||
void checkNodePermission(TransactionPermission permission, MultiIDsPolicy midPolicy) throws LedgerSecurityException; | |||||
} |
@@ -1,51 +1,51 @@ | |||||
package com.jd.blockchain.ledger.core; | |||||
public class SettingContext { | |||||
private static final TxSettingContext txSettings = new TxSettingContext(); | |||||
private static final QueryingSettingContext queryingSettings = new QueryingSettingContext(); | |||||
public static TxSettingContext txSettings() { | |||||
return txSettings; | |||||
} | |||||
public static QueryingSettingContext queryingSettings() { | |||||
return queryingSettings; | |||||
} | |||||
/** | |||||
* 与交易处理相关的设置; | |||||
* @author huanghaiquan | |||||
* | |||||
*/ | |||||
public static class TxSettingContext { | |||||
public boolean verifyLedger() { | |||||
return true; | |||||
} | |||||
public boolean verifySignature() { | |||||
return true; | |||||
} | |||||
} | |||||
/** | |||||
* 与账本查询相关的设置; | |||||
* @author huanghaiquan | |||||
* | |||||
*/ | |||||
public static class QueryingSettingContext { | |||||
/** | |||||
* 查询区块等具有 hash 标识符的对象时是否重新校验哈希; | |||||
* @return | |||||
*/ | |||||
public boolean verifyHash() { | |||||
return false; | |||||
} | |||||
} | |||||
} | |||||
//package com.jd.blockchain.ledger.core; | |||||
// | |||||
//public class SettingContext { | |||||
// | |||||
// private static final TxSettingContext txSettings = new TxSettingContext(); | |||||
// | |||||
// private static final QueryingSettingContext queryingSettings = new QueryingSettingContext(); | |||||
// | |||||
// public static TxSettingContext txSettings() { | |||||
// return txSettings; | |||||
// } | |||||
// | |||||
// public static QueryingSettingContext queryingSettings() { | |||||
// return queryingSettings; | |||||
// } | |||||
// | |||||
// /** | |||||
// * 与交易处理相关的设置; | |||||
// * @author huanghaiquan | |||||
// * | |||||
// */ | |||||
// public static class TxSettingContext { | |||||
// | |||||
// public boolean verifyLedger() { | |||||
// return true; | |||||
// } | |||||
// | |||||
// public boolean verifySignature() { | |||||
// return true; | |||||
// } | |||||
// | |||||
// } | |||||
// | |||||
// /** | |||||
// * 与账本查询相关的设置; | |||||
// * @author huanghaiquan | |||||
// * | |||||
// */ | |||||
// public static class QueryingSettingContext { | |||||
// | |||||
// /** | |||||
// * 查询区块等具有 hash 标识符的对象时是否重新校验哈希; | |||||
// * @return | |||||
// */ | |||||
// public boolean verifyHash() { | |||||
// return false; | |||||
// } | |||||
// | |||||
// } | |||||
// | |||||
//} |
@@ -1,6 +1,7 @@ | |||||
package com.jd.blockchain.ledger.core.impl; | |||||
package com.jd.blockchain.ledger.core; | |||||
import java.util.ArrayList; | import java.util.ArrayList; | ||||
import java.util.Collection; | |||||
import java.util.Iterator; | import java.util.Iterator; | ||||
import java.util.List; | import java.util.List; | ||||
@@ -15,35 +16,37 @@ import com.jd.blockchain.ledger.DataAccountDoesNotExistException; | |||||
import com.jd.blockchain.ledger.IllegalTransactionException; | import com.jd.blockchain.ledger.IllegalTransactionException; | ||||
import com.jd.blockchain.ledger.LedgerBlock; | import com.jd.blockchain.ledger.LedgerBlock; | ||||
import com.jd.blockchain.ledger.LedgerException; | 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.Operation; | ||||
import com.jd.blockchain.ledger.OperationResult; | import com.jd.blockchain.ledger.OperationResult; | ||||
import com.jd.blockchain.ledger.OperationResultData; | 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.TransactionRequest; | ||||
import com.jd.blockchain.ledger.TransactionResponse; | import com.jd.blockchain.ledger.TransactionResponse; | ||||
import com.jd.blockchain.ledger.TransactionRollbackException; | import com.jd.blockchain.ledger.TransactionRollbackException; | ||||
import com.jd.blockchain.ledger.TransactionState; | import com.jd.blockchain.ledger.TransactionState; | ||||
import com.jd.blockchain.ledger.UserDoesNotExistException; | import com.jd.blockchain.ledger.UserDoesNotExistException; | ||||
import com.jd.blockchain.ledger.core.LedgerDataSet; | |||||
import com.jd.blockchain.ledger.core.LedgerEditor; | |||||
import com.jd.blockchain.ledger.core.LedgerService; | |||||
import com.jd.blockchain.ledger.core.LedgerTransactionContext; | |||||
import com.jd.blockchain.ledger.core.OperationHandle; | |||||
import com.jd.blockchain.ledger.core.TransactionRequestContext; | |||||
import com.jd.blockchain.ledger.core.TransactionRequestExtension.Credential; | |||||
import com.jd.blockchain.service.TransactionBatchProcess; | import com.jd.blockchain.service.TransactionBatchProcess; | ||||
import com.jd.blockchain.service.TransactionBatchResult; | import com.jd.blockchain.service.TransactionBatchResult; | ||||
import com.jd.blockchain.service.TransactionBatchResultHandle; | 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.transaction.TxResponseMessage; | ||||
import com.jd.blockchain.utils.Bytes; | |||||
public class TransactionBatchProcessor implements TransactionBatchProcess { | public class TransactionBatchProcessor implements TransactionBatchProcess { | ||||
private static final Logger LOGGER = LoggerFactory.getLogger(TransactionBatchProcessor.class); | private static final Logger LOGGER = LoggerFactory.getLogger(TransactionBatchProcessor.class); | ||||
private LedgerSecurityManager securityManager; | |||||
private LedgerService ledgerService; | private LedgerService ledgerService; | ||||
private LedgerEditor newBlockEditor; | private LedgerEditor newBlockEditor; | ||||
private LedgerDataSet previousBlockDataset; | |||||
private LedgerDataQuery ledgerQueryer; | |||||
private OperationHandleRegisteration opHandles; | private OperationHandleRegisteration opHandles; | ||||
@@ -57,14 +60,15 @@ public class TransactionBatchProcessor implements TransactionBatchProcess { | |||||
private TransactionBatchResult batchResult; | private TransactionBatchResult batchResult; | ||||
/** | /** | ||||
* @param newBlockEditor 新区块的数据编辑器; | |||||
* @param previousBlockDataset 新区块的前一个区块的数据集;即未提交新区块之前的经过共识的账本最新数据集; | |||||
* @param opHandles 操作处理对象注册表; | |||||
* @param newBlockEditor 新区块的数据编辑器; | |||||
* @param ledgerQueryer 账本查询器,只包含新区块的前一个区块的数据集;即未提交新区块之前的经过共识的账本最新数据集; | |||||
* @param opHandles 操作处理对象注册表; | |||||
*/ | */ | ||||
public TransactionBatchProcessor(LedgerEditor newBlockEditor, LedgerDataSet previousBlockDataset, | |||||
OperationHandleRegisteration opHandles, LedgerService ledgerService) { | |||||
public TransactionBatchProcessor(LedgerSecurityManager securityManager, LedgerEditor newBlockEditor, | |||||
LedgerDataQuery ledgerQueryer, OperationHandleRegisteration opHandles, LedgerService ledgerService) { | |||||
this.securityManager = securityManager; | |||||
this.newBlockEditor = newBlockEditor; | this.newBlockEditor = newBlockEditor; | ||||
this.previousBlockDataset = previousBlockDataset; | |||||
this.ledgerQueryer = ledgerQueryer; | |||||
this.opHandles = opHandles; | this.opHandles = opHandles; | ||||
this.ledgerService = ledgerService; | this.ledgerService = ledgerService; | ||||
} | } | ||||
@@ -82,12 +86,26 @@ public class TransactionBatchProcessor implements TransactionBatchProcess { | |||||
try { | try { | ||||
LOGGER.debug("Start handling transaction... --[BlockHeight={}][RequestHash={}][TxHash={}]", | LOGGER.debug("Start handling transaction... --[BlockHeight={}][RequestHash={}][TxHash={}]", | ||||
newBlockEditor.getBlockHeight(), request.getHash(), request.getTransactionContent().getHash()); | newBlockEditor.getBlockHeight(), request.getHash(), request.getTransactionContent().getHash()); | ||||
TransactionRequestExtension reqExt = new TransactionRequestExtensionImpl(request); | |||||
// 初始化交易的用户安全策略; | |||||
SecurityPolicy securityPolicy = securityManager.createSecurityPolicy(reqExt.getEndpointAddresses(), | |||||
reqExt.getNodeAddresses()); | |||||
SecurityContext.setContextUsersPolicy(securityPolicy); | |||||
// 安全校验; | |||||
checkSecurity(securityPolicy); | |||||
// 验证交易请求; | |||||
checkRequest(reqExt); | |||||
// 创建交易上下文; | // 创建交易上下文; | ||||
// 此调用将会验证交易签名,验签失败将会抛出异常,同时,不记录签名错误的交易到链上; | // 此调用将会验证交易签名,验签失败将会抛出异常,同时,不记录签名错误的交易到链上; | ||||
LedgerTransactionContext txCtx = newBlockEditor.newTransaction(request); | LedgerTransactionContext txCtx = newBlockEditor.newTransaction(request); | ||||
// 处理交易; | // 处理交易; | ||||
resp = handleTx(request, txCtx); | |||||
resp = handleTx(reqExt, txCtx); | |||||
LOGGER.debug("Complete handling transaction. --[BlockHeight={}][RequestHash={}][TxHash={}]", | LOGGER.debug("Complete handling transaction. --[BlockHeight={}][RequestHash={}][TxHash={}]", | ||||
newBlockEditor.getBlockHeight(), request.getHash(), request.getTransactionContent().getHash()); | newBlockEditor.getBlockHeight(), request.getHash(), request.getTransactionContent().getHash()); | ||||
@@ -99,10 +117,9 @@ public class TransactionBatchProcessor implements TransactionBatchProcess { | |||||
"Ignore transaction caused by IllegalTransactionException! --[BlockHeight=%s][RequestHash=%s][TxHash=%s] --%s", | "Ignore transaction caused by IllegalTransactionException! --[BlockHeight=%s][RequestHash=%s][TxHash=%s] --%s", | ||||
newBlockEditor.getBlockHeight(), request.getHash(), request.getTransactionContent().getHash(), | newBlockEditor.getBlockHeight(), request.getHash(), request.getTransactionContent().getHash(), | ||||
e.getMessage()), e); | e.getMessage()), e); | ||||
} catch (BlockRollbackException e) { | } catch (BlockRollbackException e) { | ||||
// 抛弃发生处理异常的交易请求; | |||||
// resp = discard(request, TransactionState.IGNORED_BY_BLOCK_FULL_ROLLBACK); | |||||
// 发生区块级别的处理异常,向上重新抛出异常进行处理,整个区块可能被丢弃; | |||||
LOGGER.error(String.format( | LOGGER.error(String.format( | ||||
"Ignore transaction caused by BlockRollbackException! --[BlockHeight=%s][RequestHash=%s][TxHash=%s] --%s", | "Ignore transaction caused by BlockRollbackException! --[BlockHeight=%s][RequestHash=%s][TxHash=%s] --%s", | ||||
newBlockEditor.getBlockHeight(), request.getHash(), request.getTransactionContent().getHash(), | newBlockEditor.getBlockHeight(), request.getHash(), request.getTransactionContent().getHash(), | ||||
@@ -116,12 +133,79 @@ public class TransactionBatchProcessor implements TransactionBatchProcess { | |||||
newBlockEditor.getBlockHeight(), request.getHash(), request.getTransactionContent().getHash(), | newBlockEditor.getBlockHeight(), request.getHash(), request.getTransactionContent().getHash(), | ||||
e.getMessage()), e); | e.getMessage()), e); | ||||
} finally { | |||||
// 清空交易的用户安全策略; | |||||
SecurityContext.removeContextUsersPolicy(); | |||||
} | } | ||||
responseList.add(resp); | responseList.add(resp); | ||||
return resp; | return resp; | ||||
} | } | ||||
/** | |||||
* 执行安全验证; | |||||
*/ | |||||
private void checkSecurity(SecurityPolicy securityPolicy) { | |||||
// 验证节点和终端身份的合法性; | |||||
// 多重身份签署的必须全部身份都合法; | |||||
securityPolicy.checkEndpointValidity(MultiIDsPolicy.ALL); | |||||
securityPolicy.checkNodeValidity(MultiIDsPolicy.ALL); | |||||
// 验证参与方节点是否具有核准交易的权限; | |||||
securityPolicy.checkNodePermission(LedgerPermission.APPROVE_TX, MultiIDsPolicy.AT_LEAST_ONE); | |||||
} | |||||
private void checkRequest(TransactionRequestExtension reqExt) { | |||||
// TODO: 把验签和创建交易并行化; | |||||
checkTxContentHash(reqExt); | |||||
checkEndpointSignatures(reqExt); | |||||
checkNodeSignatures(reqExt); | |||||
} | |||||
private void checkTxContentHash(TransactionRequestExtension requestExt) { | |||||
TransactionContent txContent = requestExt.getTransactionContent(); | |||||
if (!TxBuilder.verifyTxContentHash(txContent, txContent.getHash())) { | |||||
// 由于哈希校验失败,引发IllegalTransactionException,使外部调用抛弃此交易请求; | |||||
throw new IllegalTransactionException( | |||||
"Wrong transaction content hash! --[TxHash=" + requestExt.getTransactionContent().getHash() + "]!", | |||||
TransactionState.IGNORED_BY_WRONG_CONTENT_SIGNATURE); | |||||
} | |||||
} | |||||
private void checkNodeSignatures(TransactionRequestExtension request) { | |||||
TransactionContent txContent = request.getTransactionContent(); | |||||
Collection<Credential> nodes = request.getNodes(); | |||||
if (nodes != null) { | |||||
for (Credential node : nodes) { | |||||
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); | |||||
} | |||||
} | |||||
} | |||||
} | |||||
private void checkEndpointSignatures(TransactionRequestExtension request) { | |||||
TransactionContent txContent = request.getTransactionContent(); | |||||
Collection<Credential> endpoints = request.getEndpoints(); | |||||
if (endpoints != null) { | |||||
for (Credential endpoint : endpoints) { | |||||
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); | |||||
} | |||||
} | |||||
} | |||||
} | |||||
/** | /** | ||||
* 处理交易;<br> | * 处理交易;<br> | ||||
* | * | ||||
@@ -131,23 +215,11 @@ public class TransactionBatchProcessor implements TransactionBatchProcess { | |||||
* @param txCtx | * @param txCtx | ||||
* @return | * @return | ||||
*/ | */ | ||||
private TransactionResponse handleTx(TransactionRequest request, LedgerTransactionContext txCtx) { | |||||
private TransactionResponse handleTx(TransactionRequestExtension request, LedgerTransactionContext txCtx) { | |||||
TransactionState result; | TransactionState result; | ||||
List<OperationResult> operationResults = new ArrayList<>(); | List<OperationResult> operationResults = new ArrayList<>(); | ||||
try { | 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!"); | |||||
} | |||||
} | |||||
LedgerDataset dataset = txCtx.getDataset(); | |||||
// 执行操作; | // 执行操作; | ||||
Operation[] ops = request.getTransactionContent().getOperations(); | Operation[] ops = request.getTransactionContent().getOperations(); | ||||
@@ -157,14 +229,14 @@ public class TransactionBatchProcessor implements TransactionBatchProcess { | |||||
// assert; Instance of operation are one of User related operations or | // assert; Instance of operation are one of User related operations or | ||||
// DataAccount related operations; | // DataAccount related operations; | ||||
OperationHandle hdl = opHandles.getHandle(operation.getClass()); | OperationHandle hdl = opHandles.getHandle(operation.getClass()); | ||||
hdl.process(operation, dataset, reqCtx, previousBlockDataset, this, ledgerService); | |||||
hdl.process(operation, dataset, request, ledgerQueryer, this, ledgerService); | |||||
} | } | ||||
}; | }; | ||||
OperationHandle opHandle; | OperationHandle opHandle; | ||||
int opIndex = 0; | int opIndex = 0; | ||||
for (Operation op : ops) { | for (Operation op : ops) { | ||||
opHandle = opHandles.getHandle(op.getClass()); | opHandle = opHandles.getHandle(op.getClass()); | ||||
BytesValue opResult = opHandle.process(op, dataset, reqCtx, previousBlockDataset, handleContext, | |||||
BytesValue opResult = opHandle.process(op, dataset, request, ledgerQueryer, handleContext, | |||||
ledgerService); | ledgerService); | ||||
if (opResult != null) { | if (opResult != null) { | ||||
operationResults.add(new OperationResultData(opIndex, opResult)); | operationResults.add(new OperationResultData(opIndex, opResult)); | ||||
@@ -183,6 +255,7 @@ public class TransactionBatchProcessor implements TransactionBatchProcess { | |||||
newBlockEditor.getBlockHeight(), request.getHash(), request.getTransactionContent().getHash(), | newBlockEditor.getBlockHeight(), request.getHash(), request.getTransactionContent().getHash(), | ||||
e.getMessage()), e); | e.getMessage()), e); | ||||
} catch (BlockRollbackException e) { | } catch (BlockRollbackException e) { | ||||
// 回滚整个区块; | |||||
result = TransactionState.IGNORED_BY_BLOCK_FULL_ROLLBACK; | result = TransactionState.IGNORED_BY_BLOCK_FULL_ROLLBACK; | ||||
txCtx.rollback(); | txCtx.rollback(); | ||||
LOGGER.error( | LOGGER.error( | ||||
@@ -201,17 +274,27 @@ public class TransactionBatchProcessor implements TransactionBatchProcess { | |||||
result = TransactionState.USER_DOES_NOT_EXIST; | result = TransactionState.USER_DOES_NOT_EXIST; | ||||
} else if (e instanceof ContractDoesNotExistException) { | } else if (e instanceof ContractDoesNotExistException) { | ||||
result = TransactionState.CONTRACT_DOES_NOT_EXIST; | result = TransactionState.CONTRACT_DOES_NOT_EXIST; | ||||
} else if (e instanceof ParticipantDoesNotExistException) { | |||||
result = TransactionState.PARTICIPANT_DOES_NOT_EXIST; | |||||
} | } | ||||
txCtx.discardAndCommit(result, operationResults); | txCtx.discardAndCommit(result, operationResults); | ||||
LOGGER.error(String.format( | 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(), | newBlockEditor.getBlockHeight(), request.getHash(), request.getTransactionContent().getHash(), | ||||
e.getMessage()), e); | e.getMessage()), e); | ||||
} catch (Exception e) { | } catch (Exception e) { | ||||
result = TransactionState.SYSTEM_ERROR; | result = TransactionState.SYSTEM_ERROR; | ||||
txCtx.discardAndCommit(TransactionState.SYSTEM_ERROR, operationResults); | txCtx.discardAndCommit(TransactionState.SYSTEM_ERROR, operationResults); | ||||
LOGGER.error(String.format( | 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(), | newBlockEditor.getBlockHeight(), request.getHash(), request.getTransactionContent().getHash(), | ||||
e.getMessage()), e); | e.getMessage()), e); | ||||
} | } |
@@ -1,16 +1,12 @@ | |||||
package com.jd.blockchain.ledger.core.impl; | |||||
package com.jd.blockchain.ledger.core; | |||||
import java.util.Map; | import java.util.Map; | ||||
import java.util.concurrent.ConcurrentHashMap; | import java.util.concurrent.ConcurrentHashMap; | ||||
import com.jd.blockchain.crypto.HashDigest; | |||||
import com.jd.blockchain.ledger.LedgerBlock; | |||||
import org.springframework.beans.factory.annotation.Autowired; | import org.springframework.beans.factory.annotation.Autowired; | ||||
import com.jd.blockchain.ledger.core.LedgerDataSet; | |||||
import com.jd.blockchain.ledger.core.LedgerEditor; | |||||
import com.jd.blockchain.ledger.core.LedgerRepository; | |||||
import com.jd.blockchain.ledger.core.LedgerService; | |||||
import com.jd.blockchain.crypto.HashDigest; | |||||
import com.jd.blockchain.ledger.LedgerBlock; | |||||
import com.jd.blockchain.service.TransactionBatchProcess; | import com.jd.blockchain.service.TransactionBatchProcess; | ||||
import com.jd.blockchain.service.TransactionEngine; | import com.jd.blockchain.service.TransactionEngine; | ||||
@@ -44,9 +40,15 @@ public class TransactionEngineImpl implements TransactionEngine { | |||||
LedgerBlock ledgerBlock = ledgerRepo.getLatestBlock(); | LedgerBlock ledgerBlock = ledgerRepo.getLatestBlock(); | ||||
LedgerEditor newBlockEditor = ledgerRepo.createNextBlock(); | LedgerEditor newBlockEditor = ledgerRepo.createNextBlock(); | ||||
LedgerDataSet previousBlockDataset = ledgerRepo.getDataSet(ledgerBlock); | |||||
batch = new InnerTransactionBatchProcessor(ledgerHash, newBlockEditor, previousBlockDataset, opHdlRegs, | |||||
ledgerService, ledgerBlock.getHeight()); | |||||
LedgerDataQuery previousBlockDataset = ledgerRepo.getDataSet(ledgerBlock); | |||||
LedgerAdminDataQuery previousAdminDataset = previousBlockDataset.getAdminDataset(); | |||||
LedgerSecurityManager securityManager = new LedgerSecurityManagerImpl( | |||||
previousAdminDataset.getAdminInfo().getRolePrivileges(), | |||||
previousAdminDataset.getAdminInfo().getUserRoles(), previousAdminDataset.getParticipantDataset(), | |||||
previousBlockDataset.getUserAccountSet()); | |||||
batch = new InnerTransactionBatchProcessor(ledgerHash, securityManager, newBlockEditor, previousBlockDataset, | |||||
opHdlRegs, ledgerService, ledgerBlock.getHeight()); | |||||
batchs.put(ledgerHash, batch); | batchs.put(ledgerHash, batch); | ||||
return batch; | return batch; | ||||
} | } | ||||
@@ -69,19 +71,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, | |||||
LedgerService ledgerService, long blockHeight) { | |||||
super(newBlockEditor, previousBlockDataset, opHandles, ledgerService); | |||||
public InnerTransactionBatchProcessor(HashDigest ledgerHash, LedgerSecurityManager securityManager, | |||||
LedgerEditor newBlockEditor, LedgerDataQuery previousBlockDataset, | |||||
OperationHandleRegisteration opHandles, LedgerService ledgerService, long blockHeight) { | |||||
super(securityManager, newBlockEditor, previousBlockDataset, opHandles, ledgerService); | |||||
this.ledgerHash = ledgerHash; | this.ledgerHash = ledgerHash; | ||||
this.blockHeight = blockHeight; | this.blockHeight = blockHeight; | ||||
} | } |
@@ -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,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; | |||||
} | |||||
} | |||||
} |
@@ -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(); | |||||
} | |||||
} |
@@ -6,6 +6,7 @@ import com.jd.blockchain.crypto.HashDigest; | |||||
import com.jd.blockchain.ledger.CryptoSetting; | import com.jd.blockchain.ledger.CryptoSetting; | ||||
import com.jd.blockchain.ledger.LedgerException; | import com.jd.blockchain.ledger.LedgerException; | ||||
import com.jd.blockchain.ledger.LedgerTransaction; | import com.jd.blockchain.ledger.LedgerTransaction; | ||||
import com.jd.blockchain.ledger.MerkleProof; | |||||
import com.jd.blockchain.ledger.TransactionState; | import com.jd.blockchain.ledger.TransactionState; | ||||
import com.jd.blockchain.storage.service.ExPolicyKVStorage; | import com.jd.blockchain.storage.service.ExPolicyKVStorage; | ||||
import com.jd.blockchain.storage.service.VersioningKVStorage; | import com.jd.blockchain.storage.service.VersioningKVStorage; | ||||
@@ -153,6 +154,10 @@ public class TransactionSet implements Transactional, MerkleProvable { | |||||
public boolean isReadonly() { | public boolean isReadonly() { | ||||
return txSet.isReadonly(); | return txSet.isReadonly(); | ||||
} | } | ||||
void setReadonly() { | |||||
txSet.setReadonly(); | |||||
} | |||||
@Override | @Override | ||||
public boolean isUpdated() { | public boolean isUpdated() { | ||||
@@ -1,4 +1,4 @@ | |||||
package com.jd.blockchain.ledger.core.impl; | |||||
package com.jd.blockchain.ledger.core; | |||||
import com.jd.blockchain.crypto.HashDigest; | import com.jd.blockchain.crypto.HashDigest; | ||||
import com.jd.blockchain.ledger.LedgerDataSnapshot; | import com.jd.blockchain.ledger.LedgerDataSnapshot; |
@@ -0,0 +1,31 @@ | |||||
package com.jd.blockchain.ledger.core; | |||||
import com.jd.blockchain.crypto.HashDigest; | |||||
import com.jd.blockchain.ledger.AccountHeader; | |||||
import com.jd.blockchain.ledger.MerkleProof; | |||||
import com.jd.blockchain.utils.Bytes; | |||||
public interface UserAccountQuery { | |||||
AccountHeader[] getAccounts(int fromIndex, int count); | |||||
/** | |||||
* 返回用户总数; | |||||
* | |||||
* @return | |||||
*/ | |||||
long getTotalCount(); | |||||
HashDigest getRootHash(); | |||||
MerkleProof getProof(Bytes key); | |||||
UserAccount getUser(String address); | |||||
UserAccount getUser(Bytes address); | |||||
boolean contains(Bytes address); | |||||
UserAccount getUser(Bytes address, long version); | |||||
} |
@@ -5,6 +5,7 @@ import com.jd.blockchain.crypto.PubKey; | |||||
import com.jd.blockchain.ledger.AccountHeader; | import com.jd.blockchain.ledger.AccountHeader; | ||||
import com.jd.blockchain.ledger.CryptoSetting; | import com.jd.blockchain.ledger.CryptoSetting; | ||||
import com.jd.blockchain.ledger.LedgerException; | import com.jd.blockchain.ledger.LedgerException; | ||||
import com.jd.blockchain.ledger.MerkleProof; | |||||
import com.jd.blockchain.storage.service.ExPolicyKVStorage; | import com.jd.blockchain.storage.service.ExPolicyKVStorage; | ||||
import com.jd.blockchain.storage.service.VersioningKVStorage; | import com.jd.blockchain.storage.service.VersioningKVStorage; | ||||
import com.jd.blockchain.utils.Bytes; | import com.jd.blockchain.utils.Bytes; | ||||
@@ -14,7 +15,7 @@ import com.jd.blockchain.utils.Transactional; | |||||
* @author huanghaiquan | * @author huanghaiquan | ||||
* | * | ||||
*/ | */ | ||||
public class UserAccountSet implements Transactional, MerkleProvable { | |||||
public class UserAccountSet implements Transactional, MerkleProvable, UserAccountQuery { | |||||
private AccountSet accountSet; | private AccountSet accountSet; | ||||
@@ -30,6 +31,7 @@ public class UserAccountSet implements Transactional, MerkleProvable { | |||||
accessPolicy); | accessPolicy); | ||||
} | } | ||||
@Override | |||||
public AccountHeader[] getAccounts(int fromIndex, int count) { | public AccountHeader[] getAccounts(int fromIndex, int count) { | ||||
return accountSet.getAccounts(fromIndex,count); | return accountSet.getAccounts(fromIndex,count); | ||||
} | } | ||||
@@ -39,6 +41,7 @@ public class UserAccountSet implements Transactional, MerkleProvable { | |||||
* | * | ||||
* @return | * @return | ||||
*/ | */ | ||||
@Override | |||||
public long getTotalCount() { | public long getTotalCount() { | ||||
return accountSet.getTotalCount(); | return accountSet.getTotalCount(); | ||||
} | } | ||||
@@ -46,6 +49,10 @@ public class UserAccountSet implements Transactional, MerkleProvable { | |||||
public boolean isReadonly() { | public boolean isReadonly() { | ||||
return accountSet.isReadonly(); | return accountSet.isReadonly(); | ||||
} | } | ||||
void setReadonly() { | |||||
accountSet.setReadonly(); | |||||
} | |||||
@Override | @Override | ||||
public HashDigest getRootHash() { | public HashDigest getRootHash() { | ||||
@@ -57,19 +64,23 @@ public class UserAccountSet implements Transactional, MerkleProvable { | |||||
return accountSet.getProof(key); | return accountSet.getProof(key); | ||||
} | } | ||||
@Override | |||||
public UserAccount getUser(String address) { | public UserAccount getUser(String address) { | ||||
return getUser(Bytes.fromBase58(address)); | return getUser(Bytes.fromBase58(address)); | ||||
} | } | ||||
@Override | |||||
public UserAccount getUser(Bytes address) { | public UserAccount getUser(Bytes address) { | ||||
BaseAccount baseAccount = accountSet.getAccount(address); | BaseAccount baseAccount = accountSet.getAccount(address); | ||||
return new UserAccount(baseAccount); | return new UserAccount(baseAccount); | ||||
} | } | ||||
@Override | |||||
public boolean contains(Bytes address) { | public boolean contains(Bytes address) { | ||||
return accountSet.contains(address); | return accountSet.contains(address); | ||||
} | } | ||||
@Override | |||||
public UserAccount getUser(Bytes address, long version) { | public UserAccount getUser(Bytes address, long version) { | ||||
BaseAccount baseAccount = accountSet.getAccount(address, version); | BaseAccount baseAccount = accountSet.getAccount(address, version); | ||||
return new UserAccount(baseAccount); | return new UserAccount(baseAccount); | ||||
@@ -0,0 +1,196 @@ | |||||
package com.jd.blockchain.ledger.core; | |||||
import java.util.Collection; | |||||
import com.jd.blockchain.binaryproto.BinaryProtocol; | |||||
import com.jd.blockchain.crypto.HashDigest; | |||||
import com.jd.blockchain.ledger.AuthorizationException; | |||||
import com.jd.blockchain.ledger.CryptoSetting; | |||||
import com.jd.blockchain.ledger.LedgerException; | |||||
import com.jd.blockchain.ledger.MerkleProof; | |||||
import com.jd.blockchain.ledger.RoleSet; | |||||
import com.jd.blockchain.ledger.RolesPolicy; | |||||
import com.jd.blockchain.ledger.UserRoles; | |||||
import com.jd.blockchain.ledger.UserRolesSettings; | |||||
import com.jd.blockchain.storage.service.ExPolicyKVStorage; | |||||
import com.jd.blockchain.storage.service.VersioningKVEntry; | |||||
import com.jd.blockchain.storage.service.VersioningKVStorage; | |||||
import com.jd.blockchain.utils.Bytes; | |||||
import com.jd.blockchain.utils.Transactional; | |||||
/** | |||||
* User-Role authorization data set; | |||||
* | |||||
* @author huanghaiquan | |||||
* | |||||
*/ | |||||
public class UserRoleDataset implements Transactional, MerkleProvable, UserRolesSettings { | |||||
private MerkleDataSet dataset; | |||||
public UserRoleDataset(CryptoSetting cryptoSetting, String prefix, ExPolicyKVStorage exPolicyStorage, | |||||
VersioningKVStorage verStorage) { | |||||
dataset = new MerkleDataSet(cryptoSetting, prefix, exPolicyStorage, verStorage); | |||||
} | |||||
public UserRoleDataset(HashDigest merkleRootHash, CryptoSetting cryptoSetting, String prefix, | |||||
ExPolicyKVStorage exPolicyStorage, VersioningKVStorage verStorage, boolean readonly) { | |||||
dataset = new MerkleDataSet(merkleRootHash, cryptoSetting, prefix, exPolicyStorage, verStorage, readonly); | |||||
} | |||||
@Override | |||||
public HashDigest getRootHash() { | |||||
return dataset.getRootHash(); | |||||
} | |||||
@Override | |||||
public MerkleProof getProof(Bytes key) { | |||||
return dataset.getProof(key); | |||||
} | |||||
@Override | |||||
public boolean isUpdated() { | |||||
return dataset.isUpdated(); | |||||
} | |||||
@Override | |||||
public void commit() { | |||||
dataset.commit(); | |||||
} | |||||
@Override | |||||
public void cancel() { | |||||
dataset.cancel(); | |||||
} | |||||
@Override | |||||
public long getUserCount() { | |||||
return dataset.getDataCount(); | |||||
} | |||||
/** | |||||
* 加入新的用户角色授权; <br> | |||||
* | |||||
* 如果该用户的授权已经存在,则引发 {@link LedgerException} 异常; | |||||
* | |||||
* @param userAddress | |||||
* @param rolesPolicy | |||||
* @param roles | |||||
*/ | |||||
@Override | |||||
public void addUserRoles(Bytes userAddress, RolesPolicy rolesPolicy, String... roles) { | |||||
UserRoles roleAuth = new UserRoles(userAddress, -1, rolesPolicy); | |||||
roleAuth.addRoles(roles); | |||||
long nv = setUserRolesAuthorization(roleAuth); | |||||
if (nv < 0) { | |||||
throw new AuthorizationException("Roles authorization of User[" + userAddress + "] already exists!"); | |||||
} | |||||
} | |||||
/** | |||||
* 加入新的用户角色授权; <br> | |||||
* | |||||
* 如果该用户的授权已经存在,则引发 {@link LedgerException} 异常; | |||||
* | |||||
* @param userAddress | |||||
* @param rolesPolicy | |||||
* @param roles | |||||
*/ | |||||
@Override | |||||
public void addUserRoles(Bytes userAddress, RolesPolicy rolesPolicy, Collection<String> roles) { | |||||
UserRoles roleAuth = new UserRoles(userAddress, -1, rolesPolicy); | |||||
roleAuth.addRoles(roles); | |||||
long nv = setUserRolesAuthorization(roleAuth); | |||||
if (nv < 0) { | |||||
throw new AuthorizationException("Roles authorization of User[" + userAddress + "] already exists!"); | |||||
} | |||||
} | |||||
/** | |||||
* 设置用户角色授权; <br> | |||||
* 如果版本校验不匹配,则返回 -1; | |||||
* | |||||
* @param userRoles | |||||
* @return | |||||
*/ | |||||
private long setUserRolesAuthorization(UserRoles userRoles) { | |||||
if (userRoles.getRoleCount() > MAX_ROLES_PER_USER) { | |||||
throw new AuthorizationException("The number of roles exceeds the maximum range!"); | |||||
} | |||||
byte[] rolesetBytes = BinaryProtocol.encode(userRoles, RoleSet.class); | |||||
return dataset.setValue(userRoles.getUserAddress(), rolesetBytes, userRoles.getVersion()); | |||||
} | |||||
/** | |||||
* 更新用户角色授权; <br> | |||||
* 如果指定用户的授权不存在,或者版本不匹配,则引发 {@link LedgerException} 异常; | |||||
* | |||||
* @param userRoles | |||||
*/ | |||||
@Override | |||||
public void updateUserRoles(UserRoles userRoles) { | |||||
long nv = setUserRolesAuthorization(userRoles); | |||||
if (nv < 0) { | |||||
throw new AuthorizationException("Update to roles of user[" + userRoles.getUserAddress() | |||||
+ "] failed due to wrong version[" + userRoles.getVersion() + "] !"); | |||||
} | |||||
} | |||||
/** | |||||
* 设置用户的角色; <br> | |||||
* 如果用户的角色授权不存在,则创建新的授权; | |||||
* | |||||
* @param userAddress 用户; | |||||
* @param policy 角色策略; | |||||
* @param roles 角色列表; | |||||
* @return | |||||
*/ | |||||
@Override | |||||
public long setRoles(Bytes userAddress, RolesPolicy policy, String... roles) { | |||||
UserRoles userRoles = getUserRoles(userAddress); | |||||
if (userRoles == null) { | |||||
userRoles = new UserRoles(userAddress, -1, policy); | |||||
} | |||||
userRoles.setPolicy(policy); | |||||
userRoles.setRoles(roles); | |||||
return setUserRolesAuthorization(userRoles); | |||||
} | |||||
/** | |||||
* 查询角色授权; | |||||
* | |||||
* <br> | |||||
* 如果不存在,则返回 null; | |||||
* | |||||
* @param address | |||||
* @return | |||||
*/ | |||||
@Override | |||||
public UserRoles getUserRoles(Bytes userAddress) { | |||||
// 只返回最新版本; | |||||
VersioningKVEntry kv = dataset.getDataEntry(userAddress); | |||||
if (kv == null) { | |||||
return null; | |||||
} | |||||
RoleSet roleSet = BinaryProtocol.decode(kv.getValue()); | |||||
return new UserRoles(userAddress, kv.getVersion(), roleSet); | |||||
} | |||||
@Override | |||||
public UserRoles[] getUserRoles() { | |||||
VersioningKVEntry[] kvEntries = dataset.getLatestDataEntries(0, (int) dataset.getDataCount()); | |||||
UserRoles[] pns = new UserRoles[kvEntries.length]; | |||||
RoleSet roleset; | |||||
for (int i = 0; i < pns.length; i++) { | |||||
roleset = BinaryProtocol.decode(kvEntries[i].getValue()); | |||||
pns[i] = new UserRoles(kvEntries[i].getKey(), kvEntries[i].getVersion(), roleset); | |||||
} | |||||
return pns; | |||||
} | |||||
@Override | |||||
public boolean isReadonly() { | |||||
return dataset.isReadonly(); | |||||
} | |||||
} |
@@ -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; | |||||
} | |||||
} |
@@ -0,0 +1,73 @@ | |||||
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.LedgerDataQuery; | |||||
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 Class<?> getOperationType() { | |||||
return SUPPORTED_OPERATION_TYPE; | |||||
} | |||||
@Override | |||||
public final BytesValue process(Operation op, LedgerDataset newBlockDataset, | |||||
TransactionRequestExtension requestContext, LedgerDataQuery previousBlockDataset, | |||||
OperationHandleContext handleContext, LedgerService ledgerService) { | |||||
// 权限校验; | |||||
SecurityPolicy securityPolicy = SecurityContext.getContextUsersPolicy(); | |||||
securityPolicy.checkEndpointPermission(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, | |||||
LedgerDataQuery previousBlockDataset, OperationHandleContext handleContext, LedgerService ledgerService); | |||||
} |
@@ -1,4 +1,4 @@ | |||||
package com.jd.blockchain.ledger.core.impl.handles; | |||||
package com.jd.blockchain.ledger.core.handles; | |||||
import org.springframework.stereotype.Service; | import org.springframework.stereotype.Service; | ||||
@@ -8,30 +8,48 @@ import com.jd.blockchain.ledger.BytesValue; | |||||
import com.jd.blockchain.ledger.ContractEventSendOperation; | import com.jd.blockchain.ledger.ContractEventSendOperation; | ||||
import com.jd.blockchain.ledger.LedgerException; | import com.jd.blockchain.ledger.LedgerException; | ||||
import com.jd.blockchain.ledger.Operation; | 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.ContractAccount; | ||||
import com.jd.blockchain.ledger.core.ContractAccountSet; | |||||
import com.jd.blockchain.ledger.core.LedgerDataSet; | |||||
import com.jd.blockchain.ledger.core.ContractAccountQuery; | |||||
import com.jd.blockchain.ledger.core.LedgerDataQuery; | |||||
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.LedgerService; | ||||
import com.jd.blockchain.ledger.core.MultiIDsPolicy; | |||||
import com.jd.blockchain.ledger.core.OperationHandle; | import com.jd.blockchain.ledger.core.OperationHandle; | ||||
import com.jd.blockchain.ledger.core.TransactionRequestContext; | |||||
import com.jd.blockchain.ledger.core.impl.LedgerQueryService; | |||||
import com.jd.blockchain.ledger.core.impl.OperationHandleContext; | |||||
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; | |||||
@Service | @Service | ||||
public abstract class AbtractContractEventHandle implements OperationHandle { | |||||
public abstract class AbtractContractEventSendOperationHandle implements OperationHandle { | |||||
@Override | @Override | ||||
public boolean support(Class<?> operationType) { | |||||
return ContractEventSendOperation.class.isAssignableFrom(operationType); | |||||
public Class<?> getOperationType() { | |||||
return ContractEventSendOperation.class; | |||||
} | } | ||||
@Override | @Override | ||||
public BytesValue process(Operation op, LedgerDataSet dataset, TransactionRequestContext requestContext, | |||||
LedgerDataSet previousBlockDataset, OperationHandleContext opHandleContext, LedgerService ledgerService) { | |||||
public BytesValue process(Operation op, LedgerDataset newBlockDataset, TransactionRequestExtension requestContext, | |||||
LedgerDataQuery previousBlockDataset, OperationHandleContext opHandleContext, LedgerService ledgerService) { | |||||
// 权限校验; | |||||
SecurityPolicy securityPolicy = SecurityContext.getContextUsersPolicy(); | |||||
securityPolicy.checkEndpointPermission(TransactionPermission.CONTRACT_OPERATION, MultiIDsPolicy.AT_LEAST_ONE); | |||||
// 操作账本; | |||||
ContractEventSendOperation contractOP = (ContractEventSendOperation) op; | ContractEventSendOperation contractOP = (ContractEventSendOperation) op; | ||||
return doProcess(requestContext, contractOP, newBlockDataset, previousBlockDataset, opHandleContext, | |||||
ledgerService); | |||||
} | |||||
private BytesValue doProcess(TransactionRequestExtension request, ContractEventSendOperation contractOP, | |||||
LedgerDataset newBlockDataset, LedgerDataQuery previousBlockDataset, OperationHandleContext opHandleContext, | |||||
LedgerService ledgerService) { | |||||
// 先从账本校验合约的有效性; | // 先从账本校验合约的有效性; | ||||
// 注意:必须在前一个区块的数据集中进行校验,因为那是经过共识的数据;从当前新区块链数据集校验则会带来攻击风险:未经共识的合约得到执行; | // 注意:必须在前一个区块的数据集中进行校验,因为那是经过共识的数据;从当前新区块链数据集校验则会带来攻击风险:未经共识的合约得到执行; | ||||
ContractAccountSet contractSet = previousBlockDataset.getContractAccountSet(); | |||||
ContractAccountQuery contractSet = previousBlockDataset.getContractAccountset(); | |||||
if (!contractSet.contains(contractOP.getContractAddress())) { | if (!contractSet.contains(contractOP.getContractAddress())) { | ||||
throw new LedgerException(String.format("Contract was not registered! --[ContractAddress=%s]", | throw new LedgerException(String.format("Contract was not registered! --[ContractAddress=%s]", | ||||
contractOP.getContractAddress())); | contractOP.getContractAddress())); | ||||
@@ -50,19 +68,17 @@ public abstract class AbtractContractEventHandle implements OperationHandle { | |||||
// 创建合约上下文; | // 创建合约上下文; | ||||
LocalContractEventContext localContractEventContext = new LocalContractEventContext( | 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); | .setLedgerContext(ledgerContext); | ||||
// 装载合约; | // 装载合约; | ||||
ContractCode contractCode = loadContractCode(contract); | ContractCode contractCode = loadContractCode(contract); | ||||
// 处理合约事件; | // 处理合约事件; | ||||
return contractCode.processEvent(localContractEventContext); | return contractCode.processEvent(localContractEventContext); | ||||
} | } | ||||
protected abstract ContractCode loadContractCode(ContractAccount contract); | |||||
protected abstract ContractCode loadContractCode(ContractAccount contract); | |||||
} | } |
@@ -0,0 +1,37 @@ | |||||
package com.jd.blockchain.ledger.core.handles; | |||||
import com.jd.blockchain.ledger.ContractCodeDeployOperation; | |||||
import com.jd.blockchain.ledger.LedgerPermission; | |||||
import com.jd.blockchain.ledger.core.LedgerDataQuery; | |||||
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.OperationHandleContext; | |||||
import com.jd.blockchain.ledger.core.SecurityContext; | |||||
import com.jd.blockchain.ledger.core.SecurityPolicy; | |||||
import com.jd.blockchain.ledger.core.TransactionRequestExtension; | |||||
public class ContractCodeDeployOperationHandle extends AbstractLedgerOperationHandle<ContractCodeDeployOperation> { | |||||
public ContractCodeDeployOperationHandle() { | |||||
super(ContractCodeDeployOperation.class); | |||||
} | |||||
@Override | |||||
protected void doProcess(ContractCodeDeployOperation op, LedgerDataset newBlockDataset, | |||||
TransactionRequestExtension requestContext, LedgerDataQuery previousBlockDataset, | |||||
OperationHandleContext handleContext, LedgerService ledgerService) { | |||||
// TODO: 校验合约代码的正确性; | |||||
// TODO: 请求者应该提供合约账户的公钥签名,以确保注册人对注册的地址和公钥具有合法的使用权; | |||||
// 权限校验; | |||||
SecurityPolicy securityPolicy = SecurityContext.getContextUsersPolicy(); | |||||
securityPolicy.checkEndpointPermission(LedgerPermission.UPGRADE_CONTRACT, MultiIDsPolicy.AT_LEAST_ONE); | |||||
// 操作账本; | |||||
ContractCodeDeployOperation contractOP = (ContractCodeDeployOperation) op; | |||||
newBlockDataset.getContractAccountset().deploy(contractOP.getContractID().getAddress(), | |||||
contractOP.getContractID().getPubKey(), contractOP.getAddressSignature(), contractOP.getChainCode()); | |||||
} | |||||
} |
@@ -1,4 +1,4 @@ | |||||
package com.jd.blockchain.ledger.core.impl.handles; | |||||
package com.jd.blockchain.ledger.core.handles; | |||||
import java.util.ArrayList; | import java.util.ArrayList; | ||||
import java.util.List; | import java.util.List; | ||||
@@ -6,7 +6,7 @@ import java.util.List; | |||||
import com.jd.blockchain.contract.LedgerContext; | import com.jd.blockchain.contract.LedgerContext; | ||||
import com.jd.blockchain.crypto.HashDigest; | import com.jd.blockchain.crypto.HashDigest; | ||||
import com.jd.blockchain.ledger.*; | import com.jd.blockchain.ledger.*; | ||||
import com.jd.blockchain.ledger.core.impl.OperationHandleContext; | |||||
import com.jd.blockchain.ledger.core.OperationHandleContext; | |||||
import com.jd.blockchain.transaction.BlockchainQueryService; | import com.jd.blockchain.transaction.BlockchainQueryService; | ||||
import com.jd.blockchain.transaction.DataAccountKVSetOperationBuilder; | import com.jd.blockchain.transaction.DataAccountKVSetOperationBuilder; | ||||
import com.jd.blockchain.transaction.DataAccountRegisterOperationBuilder; | import com.jd.blockchain.transaction.DataAccountRegisterOperationBuilder; | ||||
@@ -38,6 +38,11 @@ public class ContractLedgerContext implements LedgerContext { | |||||
public LedgerInfo getLedger(HashDigest ledgerHash) { | public LedgerInfo getLedger(HashDigest ledgerHash) { | ||||
return innerQueryService.getLedger(ledgerHash); | return innerQueryService.getLedger(ledgerHash); | ||||
} | } | ||||
@Override | |||||
public LedgerAdminInfo getLedgerAdminInfo(HashDigest ledgerHash) { | |||||
return innerQueryService.getLedgerAdminInfo(ledgerHash); | |||||
} | |||||
@Override | @Override | ||||
public ParticipantNode[] getConsensusParticipants(HashDigest ledgerHash) { | public ParticipantNode[] getConsensusParticipants(HashDigest ledgerHash) { |
@@ -0,0 +1,47 @@ | |||||
package com.jd.blockchain.ledger.core.handles; | |||||
import com.jd.blockchain.ledger.DataAccountDoesNotExistException; | |||||
import com.jd.blockchain.ledger.DataAccountKVSetOperation; | |||||
import com.jd.blockchain.ledger.DataAccountKVSetOperation.KVWriteEntry; | |||||
import com.jd.blockchain.ledger.DataVersionConflictException; | |||||
import com.jd.blockchain.ledger.LedgerPermission; | |||||
import com.jd.blockchain.ledger.core.DataAccount; | |||||
import com.jd.blockchain.ledger.core.LedgerDataQuery; | |||||
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.OperationHandleContext; | |||||
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 DataAccountKVSetOperationHandle extends AbstractLedgerOperationHandle<DataAccountKVSetOperation> { | |||||
public DataAccountKVSetOperationHandle() { | |||||
super(DataAccountKVSetOperation.class); | |||||
} | |||||
@Override | |||||
protected void doProcess(DataAccountKVSetOperation kvWriteOp, LedgerDataset newBlockDataset, | |||||
TransactionRequestExtension requestContext, LedgerDataQuery previousBlockDataset, | |||||
OperationHandleContext handleContext, LedgerService ledgerService) { | |||||
// 权限校验; | |||||
SecurityPolicy securityPolicy = SecurityContext.getContextUsersPolicy(); | |||||
securityPolicy.checkEndpointPermission(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!"); | |||||
} | |||||
KVWriteEntry[] writeSet = kvWriteOp.getWriteSet(); | |||||
long v = -1; | |||||
for (KVWriteEntry kvw : writeSet) { | |||||
v = account.setBytes(Bytes.fromString(kvw.getKey()), kvw.getValue(), kvw.getExpectedVersion()); | |||||
if (v < 0) { | |||||
throw new DataVersionConflictException(); | |||||
} | |||||
} | |||||
} | |||||
} |
@@ -0,0 +1,36 @@ | |||||
package com.jd.blockchain.ledger.core.handles; | |||||
import com.jd.blockchain.ledger.BlockchainIdentity; | |||||
import com.jd.blockchain.ledger.DataAccountRegisterOperation; | |||||
import com.jd.blockchain.ledger.LedgerPermission; | |||||
import com.jd.blockchain.ledger.core.LedgerDataQuery; | |||||
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.OperationHandleContext; | |||||
import com.jd.blockchain.ledger.core.SecurityContext; | |||||
import com.jd.blockchain.ledger.core.SecurityPolicy; | |||||
import com.jd.blockchain.ledger.core.TransactionRequestExtension; | |||||
public class DataAccountRegisterOperationHandle extends AbstractLedgerOperationHandle<DataAccountRegisterOperation> { | |||||
public DataAccountRegisterOperationHandle() { | |||||
super(DataAccountRegisterOperation.class); | |||||
} | |||||
@Override | |||||
protected void doProcess(DataAccountRegisterOperation op, LedgerDataset newBlockDataset, | |||||
TransactionRequestExtension requestContext, LedgerDataQuery previousBlockDataset, | |||||
OperationHandleContext handleContext, LedgerService ledgerService) { | |||||
// TODO: 请求者应该提供数据账户的公钥签名,以更好地确保注册人对该地址和公钥具有合法使用权; | |||||
// 权限校验; | |||||
SecurityPolicy securityPolicy = SecurityContext.getContextUsersPolicy(); | |||||
securityPolicy.checkEndpointPermission(LedgerPermission.REGISTER_DATA_ACCOUNT, MultiIDsPolicy.AT_LEAST_ONE); | |||||
// 操作账本; | |||||
DataAccountRegisterOperation dataAccountRegOp = (DataAccountRegisterOperation) op; | |||||
BlockchainIdentity bid = dataAccountRegOp.getAccountID(); | |||||
newBlockDataset.getDataAccountSet().register(bid.getAddress(), bid.getPubKey(), null); | |||||
} | |||||
} |
@@ -1,13 +1,13 @@ | |||||
package com.jd.blockchain.ledger.core.impl.handles; | |||||
package com.jd.blockchain.ledger.core.handles; | |||||
import static com.jd.blockchain.utils.BaseConstant.CONTRACT_SERVICE_PROVIDER; | |||||
import com.jd.blockchain.contract.engine.ContractCode; | import com.jd.blockchain.contract.engine.ContractCode; | ||||
import com.jd.blockchain.contract.engine.ContractEngine; | import com.jd.blockchain.contract.engine.ContractEngine; | ||||
import com.jd.blockchain.contract.engine.ContractServiceProviders; | import com.jd.blockchain.contract.engine.ContractServiceProviders; | ||||
import com.jd.blockchain.ledger.core.ContractAccount; | import com.jd.blockchain.ledger.core.ContractAccount; | ||||
import static com.jd.blockchain.utils.BaseConstant.CONTRACT_SERVICE_PROVIDER; | |||||
public class JVMContractEventSendOperationHandle extends AbtractContractEventHandle { | |||||
public class JVMContractEventSendOperationHandle extends AbtractContractEventSendOperationHandle { | |||||
private static final ContractEngine JVM_ENGINE; | private static final ContractEngine JVM_ENGINE; | ||||
@@ -26,12 +26,4 @@ public class JVMContractEventSendOperationHandle extends AbtractContractEventHan | |||||
return contractCode; | 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; | |||||
// } | |||||
} | } |
@@ -0,0 +1,27 @@ | |||||
package com.jd.blockchain.ledger.core.handles; | |||||
import com.jd.blockchain.ledger.BytesValue; | |||||
import com.jd.blockchain.ledger.LedgerInitOperation; | |||||
import com.jd.blockchain.ledger.Operation; | |||||
import com.jd.blockchain.ledger.core.LedgerDataQuery; | |||||
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.OperationHandleContext; | |||||
import com.jd.blockchain.ledger.core.TransactionRequestExtension; | |||||
public class LedgerInitOperationHandle implements OperationHandle { | |||||
@Override | |||||
public Class<?> getOperationType() { | |||||
return LedgerInitOperation.class; | |||||
} | |||||
@Override | |||||
public BytesValue process(Operation op, LedgerDataset newBlockDataset, TransactionRequestExtension requestContext, | |||||
LedgerDataQuery previousBlockDataset, OperationHandleContext handleContext, LedgerService ledgerService) { | |||||
// 对初始化操作不需要做任何处理; | |||||
return null; | |||||
} | |||||
} |
@@ -0,0 +1,50 @@ | |||||
package com.jd.blockchain.ledger.core.handles; | |||||
import com.jd.blockchain.ledger.LedgerPermission; | |||||
import com.jd.blockchain.ledger.RolePrivilegeSettings; | |||||
import com.jd.blockchain.ledger.RolePrivileges; | |||||
import com.jd.blockchain.ledger.RolesConfigureOperation; | |||||
import com.jd.blockchain.ledger.RolesConfigureOperation.RolePrivilegeEntry; | |||||
import com.jd.blockchain.ledger.core.LedgerDataQuery; | |||||
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.OperationHandleContext; | |||||
import com.jd.blockchain.ledger.core.SecurityContext; | |||||
import com.jd.blockchain.ledger.core.SecurityPolicy; | |||||
import com.jd.blockchain.ledger.core.TransactionRequestExtension; | |||||
public class RolesConfigureOperationHandle extends AbstractLedgerOperationHandle<RolesConfigureOperation> { | |||||
public RolesConfigureOperationHandle() { | |||||
super(RolesConfigureOperation.class); | |||||
} | |||||
@Override | |||||
protected void doProcess(RolesConfigureOperation operation, LedgerDataset newBlockDataset, | |||||
TransactionRequestExtension request, LedgerDataQuery previousBlockDataset, | |||||
OperationHandleContext handleContext, LedgerService ledgerService) { | |||||
// 权限校验; | |||||
SecurityPolicy securityPolicy = SecurityContext.getContextUsersPolicy(); | |||||
securityPolicy.checkEndpointPermission(LedgerPermission.CONFIGURE_ROLES, MultiIDsPolicy.AT_LEAST_ONE); | |||||
// 操作账本; | |||||
RolePrivilegeEntry[] rpcfgs = operation.getRoles(); | |||||
RolePrivilegeSettings rpSettings = newBlockDataset.getAdminDataset().getRolePrivileges(); | |||||
if (rpcfgs != null) { | |||||
for (RolePrivilegeEntry rpcfg : rpcfgs) { | |||||
RolePrivileges rp = rpSettings.getRolePrivilege(rpcfg.getRoleName()); | |||||
if (rp == null) { | |||||
rpSettings.addRolePrivilege(rpcfg.getRoleName(), rpcfg.getEnableLedgerPermissions(), | |||||
rpcfg.getEnableTransactionPermissions()); | |||||
} else { | |||||
rp.enable(rpcfg.getEnableLedgerPermissions()); | |||||
rp.enable(rpcfg.getEnableTransactionPermissions()); | |||||
rp.disable(rpcfg.getDisableLedgerPermissions()); | |||||
rp.disable(rpcfg.getDisableTransactionPermissions()); | |||||
} | |||||
} | |||||
} | |||||
} | |||||
} |
@@ -0,0 +1,78 @@ | |||||
package com.jd.blockchain.ledger.core.handles; | |||||
import java.util.ArrayList; | |||||
import java.util.List; | |||||
import com.jd.blockchain.ledger.LedgerPermission; | |||||
import com.jd.blockchain.ledger.RolePrivilegeSettings; | |||||
import com.jd.blockchain.ledger.RolesPolicy; | |||||
import com.jd.blockchain.ledger.UserAuthorizeOperation; | |||||
import com.jd.blockchain.ledger.UserAuthorizeOperation.UserRolesEntry; | |||||
import com.jd.blockchain.ledger.UserRoles; | |||||
import com.jd.blockchain.ledger.UserRolesSettings; | |||||
import com.jd.blockchain.ledger.core.LedgerDataQuery; | |||||
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.OperationHandleContext; | |||||
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 UserAuthorizeOperationHandle extends AbstractLedgerOperationHandle<UserAuthorizeOperation> { | |||||
public UserAuthorizeOperationHandle() { | |||||
super(UserAuthorizeOperation.class); | |||||
} | |||||
@Override | |||||
protected void doProcess(UserAuthorizeOperation operation, LedgerDataset newBlockDataset, | |||||
TransactionRequestExtension request, LedgerDataQuery previousBlockDataset, | |||||
OperationHandleContext handleContext, LedgerService ledgerService) { | |||||
// 权限校验; | |||||
SecurityPolicy securityPolicy = SecurityContext.getContextUsersPolicy(); | |||||
securityPolicy.checkEndpointPermission(LedgerPermission.CONFIGURE_ROLES, MultiIDsPolicy.AT_LEAST_ONE); | |||||
// 操作账本; | |||||
UserRolesEntry[] urcfgs = operation.getUserRolesAuthorizations(); | |||||
UserRolesSettings urSettings = newBlockDataset.getAdminDataset().getUserRoles(); | |||||
RolePrivilegeSettings rolesSettings = newBlockDataset.getAdminDataset().getRolePrivileges(); | |||||
if (urcfgs != null) { | |||||
for (UserRolesEntry urcfg : urcfgs) { | |||||
// | |||||
String[] authRoles = urcfg.getAuthorizedRoles(); | |||||
List<String> validRoles = new ArrayList<String>(); | |||||
if (authRoles != null) { | |||||
for (String r : authRoles) { | |||||
if (rolesSettings.contains(r)) { | |||||
validRoles.add(r); | |||||
} | |||||
} | |||||
} | |||||
for (Bytes address : urcfg.getUserAddresses()) { | |||||
UserRoles ur = urSettings.getUserRoles(address); | |||||
if (ur == null) { | |||||
// 这是新的授权; | |||||
RolesPolicy policy = urcfg.getPolicy(); | |||||
if (policy == null) { | |||||
policy = RolesPolicy.UNION; | |||||
} | |||||
urSettings.addUserRoles(address, policy, validRoles); | |||||
} else { | |||||
// 更改之前的授权; | |||||
ur.addRoles(validRoles); | |||||
ur.removeRoles(urcfg.getUnauthorizedRoles()); | |||||
// 如果请求中设置了策略,才进行更新; | |||||
RolesPolicy policy = urcfg.getPolicy(); | |||||
if (policy != null) { | |||||
ur.setPolicy(policy); | |||||
} | |||||
} | |||||
} | |||||
} | |||||
} | |||||
} | |||||
} |
@@ -0,0 +1,38 @@ | |||||
package com.jd.blockchain.ledger.core.handles; | |||||
import com.jd.blockchain.ledger.BlockchainIdentity; | |||||
import com.jd.blockchain.ledger.LedgerPermission; | |||||
import com.jd.blockchain.ledger.UserRegisterOperation; | |||||
import com.jd.blockchain.ledger.core.LedgerDataQuery; | |||||
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.OperationHandleContext; | |||||
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 extends AbstractLedgerOperationHandle<UserRegisterOperation> { | |||||
public UserRegisterOperationHandle() { | |||||
super(UserRegisterOperation.class); | |||||
} | |||||
@Override | |||||
protected void doProcess(UserRegisterOperation op, LedgerDataset newBlockDataset, | |||||
TransactionRequestExtension requestContext, LedgerDataQuery previousBlockDataset, | |||||
OperationHandleContext handleContext, LedgerService ledgerService) { | |||||
// 权限校验; | |||||
SecurityPolicy securityPolicy = SecurityContext.getContextUsersPolicy(); | |||||
securityPolicy.checkEndpointPermission(LedgerPermission.REGISTER_USER, MultiIDsPolicy.AT_LEAST_ONE); | |||||
// 操作账本; | |||||
UserRegisterOperation userRegOp = (UserRegisterOperation) op; | |||||
BlockchainIdentity bid = userRegOp.getUserID(); | |||||
Bytes userAddress = bid.getAddress(); | |||||
newBlockDataset.getUserAccountSet().register(userAddress, bid.getPubKey()); | |||||
} | |||||
} |
@@ -1,9 +0,0 @@ | |||||
package com.jd.blockchain.ledger.core.impl; | |||||
import com.jd.blockchain.ledger.TransactionState; | |||||
import com.jd.blockchain.ledger.LedgerTransaction; | |||||
import com.jd.blockchain.ledger.TransactionRequest; | |||||
import com.jd.blockchain.ledger.core.LedgerDataSet; | |||||
import com.jd.blockchain.ledger.core.LedgerTransactionContext; | |||||
import com.jd.blockchain.storage.service.utils.BufferedKVStorage; | |||||