Browse Source

Implements storage that separates LedgerSetting from LedgerMetadata;

tags/1.1.0
huanghaiquan 5 years ago
parent
commit
e68e499635
8 changed files with 178 additions and 76 deletions
  1. +105
    -44
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerAdminAccount.java
  2. +3
    -3
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerConfiguration.java
  3. +1
    -1
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerRepositoryImpl.java
  4. +2
    -2
      source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/impl/LedgerTransactionalEditor.java
  5. +3
    -3
      source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerMetaDataTest.java
  6. +36
    -22
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/LedgerMetadata.java
  7. +27
    -0
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/LedgerMetadata_V2.java
  8. +1
    -1
      source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/LedgerSettings.java

+ 105
- 44
source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerAdminAccount.java View File

@@ -1,7 +1,7 @@
package com.jd.blockchain.ledger.core;
import com.jd.blockchain.ledger.LedgerMetadata;
import com.jd.blockchain.ledger.LedgerSetting;
import com.jd.blockchain.ledger.LedgerSettings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -29,9 +29,11 @@ public class LedgerAdminAccount implements Transactional, LedgerAdministration {
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_PRIVILEGE_PREFIX = "PVL" + LedgerConsts.KEY_SEPERATOR;
public static final String LEDGER_SETTING_PREFIX = "SET" + LedgerConsts.KEY_SEPERATOR;
public static final String LEDGER_PRIVILEGE_PREFIX = "PRL" + LedgerConsts.KEY_SEPERATOR;
private final Bytes metaPrefix;
private final Bytes settingPrefix;
private final Bytes privilegePrefix;
private LedgerMetadata origMetadata;
@@ -44,19 +46,26 @@ public class LedgerAdminAccount implements Transactional, LedgerAdministration {
* <br>
* 对 LedgerMetadata 修改的新配置不能立即生效,需要达成共识后,在下一次区块计算中才生效;
*/
private LedgerSetting previousSetting;
private LedgerSettings previousSettings;
private HashDigest previousSettingHash;
/**
* 账本的参与节点;
*/
private ParticipantDataSet participants;
/**
* 账本参数配置;
*/
private LedgerSettings settings;
// /**
// * 账本的全局权限设置;
// */
// private PrivilegeDataSet privileges;
private ExPolicyKVStorage settingsStorage;
private ExPolicyKVStorage storage;
private HashDigest adminAccountHash;
@@ -80,7 +89,7 @@ public class LedgerAdminAccount implements Transactional, LedgerAdministration {
* 只在新建账本时调用此方法;
*
* @param ledgerSeed
* @param setting
* @param settings
* @param partiList
* @param exPolicyStorage
* @param versioningStorage
@@ -88,6 +97,7 @@ public class LedgerAdminAccount implements Transactional, LedgerAdministration {
public LedgerAdminAccount(LedgerInitSetting initSetting, String keyPrefix, ExPolicyKVStorage exPolicyStorage,
VersioningKVStorage versioningStorage) {
this.metaPrefix = Bytes.fromString(keyPrefix + LEDGER_META_PREFIX);
this.settingPrefix = Bytes.fromString(keyPrefix + LEDGER_SETTING_PREFIX);
this.privilegePrefix = Bytes.fromString(keyPrefix + LEDGER_PRIVILEGE_PREFIX);
ParticipantNode[] parties = initSetting.getConsensusParticipants();
@@ -108,15 +118,15 @@ public class LedgerAdminAccount implements Transactional, LedgerAdministration {
this.metadata = new LedgerMetadataImpl();
this.metadata.setSeed(initSetting.getLedgerSeed());
// 新配置;
this.metadata.setting = new LedgerConfiguration(initSetting.getConsensusProvider(),
initSetting.getConsensusSettings(), initSetting.getCryptoSetting());
this.previousSetting = new LedgerConfiguration(initSetting.getConsensusProvider(),
initSetting.getConsensusSettings(), initSetting.getCryptoSetting());
this.settings = new LedgerConfiguration(initSetting.getConsensusProvider(), initSetting.getConsensusSettings(),
initSetting.getCryptoSetting());
this.previousSettings = new LedgerConfiguration(settings);
this.previousSettingHash = null;
this.adminAccountHash = null;
// 基于原配置初始化参与者列表;
String partiPrefix = keyPrefix + LEDGER_PARTICIPANT_PREFIX;
this.participants = new ParticipantDataSet(previousSetting.getCryptoSetting(), partiPrefix, exPolicyStorage,
this.participants = new ParticipantDataSet(previousSettings.getCryptoSetting(), partiPrefix, exPolicyStorage,
versioningStorage);
for (ParticipantNode p : parties) {
@@ -124,20 +134,23 @@ public class LedgerAdminAccount implements Transactional, LedgerAdministration {
}
// 初始化其它属性;
this.settingsStorage = exPolicyStorage;
this.storage = exPolicyStorage;
this.readonly = false;
}
public LedgerAdminAccount(HashDigest adminAccountHash, String keyPrefix, ExPolicyKVStorage kvStorage,
VersioningKVStorage versioningKVStorage, boolean readonly) {
this.metaPrefix = Bytes.fromString(keyPrefix + LEDGER_META_PREFIX);
this.settingPrefix = Bytes.fromString(keyPrefix + LEDGER_SETTING_PREFIX);
this.privilegePrefix = Bytes.fromString(keyPrefix + LEDGER_PRIVILEGE_PREFIX);
this.settingsStorage = kvStorage;
this.storage = kvStorage;
this.readonly = readonly;
this.origMetadata = loadAndVerifySettings(adminAccountHash);
this.origMetadata = loadAndVerifyMetadata(adminAccountHash);
this.metadata = new LedgerMetadataImpl(origMetadata);
this.settings = loadAndVerifySettings(metadata.getSettingsHash());
// 复制记录一份配置作为上一个区块的原始配置,该实例仅供读取,不做修改,也不会回写到存储;
this.previousSetting = new LedgerConfiguration(metadata.getSetting());
this.previousSettings = new LedgerConfiguration(settings);
this.previousSettingHash = metadata.getSettingsHash();
this.adminAccountHash = adminAccountHash;
// this.privileges = new PrivilegeDataSet(metadata.getPrivilegesHash(),
// metadata.getSetting().getCryptoSetting(),
@@ -151,23 +164,49 @@ public class LedgerAdminAccount implements Transactional, LedgerAdministration {
// PrefixAppender.prefix(LEDGER_PARTICIPANT_PREFIX, versioningKVStorage),
// readonly);
String partiPrefix = keyPrefix + LEDGER_PARTICIPANT_PREFIX;
this.participants = new ParticipantDataSet(metadata.getParticipantsHash(), previousSetting.getCryptoSetting(),
this.participants = new ParticipantDataSet(metadata.getParticipantsHash(), previousSettings.getCryptoSetting(),
partiPrefix, kvStorage, versioningKVStorage, readonly);
}
private LedgerMetadata loadAndVerifySettings(HashDigest adminAccountHash) {
// String base58Hash = adminAccountHash.toBase58();
// String key = encodeMetadataKey(base58Hash);
private LedgerSettings loadAndVerifySettings(HashDigest settingsHash) {
if (settingsHash == null) {
return null;
}
Bytes key = encodeSettingsKey(settingsHash);
byte[] bytes = storage.get(key);
HashFunction hashFunc = Crypto.getHashFunction(adminAccountHash.getAlgorithm());
if (!hashFunc.verify(adminAccountHash, 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 loadAndVerifyMetadata(HashDigest adminAccountHash) {
Bytes key = encodeMetadataKey(adminAccountHash);
byte[] bytes = settingsStorage.get(key);
byte[] bytes = storage.get(key);
HashFunction hashFunc = Crypto.getHashFunction(adminAccountHash.getAlgorithm());
if (!hashFunc.verify(adminAccountHash, bytes)) {
LOGGER.error("The hash verification of ledger settings fail! --[HASH=" + key + "]");
throw new LedgerException("The hash verification of ledger settings fail!");
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;
@@ -188,12 +227,12 @@ public class LedgerAdminAccount implements Transactional, LedgerAdministration {
* 返回原来的账本配置;
*
* <br>
* 此方法总是返回从上一个区块加载的账本配置,即时调用 {@link #setLedgerSetting(LedgerSetting)} 做出了新的更改;
* 此方法总是返回从上一个区块加载的账本配置,即时调用 {@link #setLedgerSetting(LedgerSettings)} 做出了新的更改;
*
* @return
*/
public LedgerSetting getPreviousSetting() {
return previousSetting;
public LedgerSettings getPreviousSetting() {
return previousSettings;
}
/**
@@ -201,8 +240,8 @@ public class LedgerAdminAccount implements Transactional, LedgerAdministration {
*
* @return
*/
public LedgerSetting getSetting() {
return metadata.getSetting();
public LedgerSettings getSetting() {
return settings;
}
/**
@@ -210,11 +249,12 @@ public class LedgerAdminAccount implements Transactional, LedgerAdministration {
*
* @param ledgerSetting
*/
public void setLedgerSetting(LedgerSetting ledgerSetting) {
public void setLedgerSetting(LedgerSettings ledgerSetting) {
if (readonly) {
throw new IllegalArgumentException("This merkle dataset is readonly!");
}
metadata.setSetting(ledgerSetting);
settings = ledgerSetting;
updated = true;
}
@Override
@@ -259,14 +299,34 @@ public class LedgerAdminAccount implements Transactional, LedgerAdministration {
if (!isUpdated()) {
return;
}
// 计算并更新参与方集合的根哈希;
participants.commit();
metadata.setParticipantsHash(participants.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);
HashFunction hashFunc = Crypto
.getHashFunction(previousSetting.getCryptoSetting().getHashAlgorithm());
HashDigest metadataHash = hashFunc.hash(metadataBytes);
if (adminAccountHash == null || !adminAccountHash.equals(metadataHash)) {
// update modify;
@@ -274,14 +334,13 @@ public class LedgerAdminAccount implements Transactional, LedgerAdministration {
// String metadataKey = encodeMetadataKey(base58MetadataHash);
Bytes metadataKey = encodeMetadataKey(metadataHash);
boolean nx = settingsStorage.set(metadataKey, metadataBytes, ExPolicy.NOT_EXISTING);
boolean nx = storage.set(metadataKey, metadataBytes, ExPolicy.NOT_EXISTING);
if (!nx) {
String base58MetadataHash = metadataHash.toBase58();
// 有可能发生了并发写入冲突,不同的节点都向同一个存储服务器上写入数据;
// throw new LedgerException(
// "Ledger metadata already exist! --[LedgerMetadataHash=" + base58MetadataHash
// + "]");
// LOGGER.warn("Ledger metadata already exist! --[MetadataHash=" +
// base58MetadataHash + "]");
String errMsg = "Ledger metadata already exist! --[MetadataHash=" + base58MetadataHash + "]";
LOGGER.warn(errMsg);
throw new LedgerException(errMsg);
}
adminAccountHash = metadataHash;
@@ -311,17 +370,20 @@ public class LedgerAdminAccount implements Transactional, LedgerAdministration {
private byte[] seed;
private LedgerSetting setting;
// private LedgerSetting setting;
private HashDigest participantsHash;
private HashDigest settingsHash;
public LedgerMetadataImpl() {
}
public LedgerMetadataImpl(LedgerMetadata metadata) {
this.seed = metadata.getSeed();
this.setting = metadata.getSetting();
// this.setting = metadata.getSetting();
this.participantsHash = metadata.getParticipantsHash();
this.settingsHash = metadata.getSettingsHash();
}
@Override
@@ -330,8 +392,8 @@ public class LedgerAdminAccount implements Transactional, LedgerAdministration {
}
@Override
public LedgerSetting getSetting() {
return setting;
public HashDigest getSettingsHash() {
return settingsHash;
}
@Override
@@ -343,9 +405,8 @@ public class LedgerAdminAccount implements Transactional, LedgerAdministration {
this.seed = seed;
}
public void setSetting(LedgerSetting setting) {
// copy a new instance;
this.setting = new LedgerConfiguration(setting);
public void setSettingsHash(HashDigest settingHash) {
this.settingsHash = settingHash;
}
public void setParticipantsHash(HashDigest participantsHash) {


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

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

import com.jd.blockchain.ledger.CryptoSetting;
import com.jd.blockchain.ledger.LedgerSetting;
import com.jd.blockchain.ledger.LedgerSettings;
import com.jd.blockchain.utils.Bytes;

public class LedgerConfiguration implements LedgerSetting {
public class LedgerConfiguration implements LedgerSettings {

private String consensusProvider;

@@ -16,7 +16,7 @@ public class LedgerConfiguration implements LedgerSetting {
this.cryptoSetting = new CryptoConfig();
}

public LedgerConfiguration(LedgerSetting origSetting) {
public LedgerConfiguration(LedgerSettings origSetting) {
if (origSetting != null) {
this.consensusProvider = origSetting.getConsensusProvider();
this.consensusSetting = origSetting.getConsensusSetting();


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

@@ -478,7 +478,7 @@ public class LedgerRepositoryImpl implements LedgerRepository {
return newDataSet;
}

static TransactionSet newTransactionSet(LedgerSetting ledgerSetting, String keyPrefix,
static TransactionSet newTransactionSet(LedgerSettings ledgerSetting, String keyPrefix,
ExPolicyKVStorage ledgerExStorage, VersioningKVStorage ledgerVerStorage) {
// TransactionSet transactionSet = new
// TransactionSet(ledgerSetting.getCryptoSetting(),


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

@@ -13,7 +13,7 @@ import com.jd.blockchain.ledger.IllegalTransactionException;
import com.jd.blockchain.ledger.LedgerBlock;
import com.jd.blockchain.ledger.LedgerDataSnapshot;
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.OperationResult;
import com.jd.blockchain.ledger.TransactionContent;
@@ -115,7 +115,7 @@ public class LedgerTransactionalEditor implements LedgerEditor {
* @param verifyTx 是否校验交易请求;当外部调用者在调用前已经实施了验证时,将次参数设置为 false 能够提升性能;
* @return
*/
public static LedgerTransactionalEditor createEditor(LedgerBlock previousBlock, LedgerSetting ledgerSetting,
public static LedgerTransactionalEditor createEditor(LedgerBlock previousBlock, LedgerSettings ledgerSetting,
String ledgerKeyPrefix, ExPolicyKVStorage ledgerExStorage, VersioningKVStorage ledgerVerStorage) {
// new block;
HashDigest ledgerHash = previousBlock.getLedgerHash();


+ 3
- 3
source/ledger/ledger-core/src/test/java/test/com/jd/blockchain/ledger/LedgerMetaDataTest.java View File

@@ -8,7 +8,7 @@ import static org.junit.Assert.assertTrue;
import java.util.Random;

import com.jd.blockchain.ledger.LedgerMetadata;
import com.jd.blockchain.ledger.LedgerSetting;
import com.jd.blockchain.ledger.LedgerSettings;
import org.junit.Before;
import org.junit.Test;

@@ -119,8 +119,8 @@ public class LedgerMetaDataTest {

LedgerConfiguration ledgerConfiguration = new LedgerConfiguration(consensusProvider, new Bytes(csSettingsBytes),
cryptoConfig);
byte[] encodeBytes = BinaryProtocol.encode(ledgerConfiguration, LedgerSetting.class);
LedgerSetting deLedgerConfiguration = BinaryProtocol.decode(encodeBytes);
byte[] encodeBytes = BinaryProtocol.encode(ledgerConfiguration, LedgerSettings.class);
LedgerSettings deLedgerConfiguration = BinaryProtocol.decode(encodeBytes);
// verify start
assertTrue(ledgerConfiguration.getConsensusSetting().equals(deLedgerConfiguration.getConsensusSetting()));
assertEquals(ledgerConfiguration.getCryptoSetting().getAutoVerifyHash(),


+ 36
- 22
source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/LedgerMetadata.java View File

@@ -6,31 +6,45 @@ import com.jd.blockchain.binaryproto.PrimitiveType;
import com.jd.blockchain.consts.DataCodes;
import com.jd.blockchain.crypto.HashDigest;

@DataContract(code = DataCodes.METADATA)
/**
* 账本的元数据;
*
* @author huanghaiquan
*
*/
@DataContract(code = DataCodes.METADATA, name = "LEDGER-METADATA")
public interface LedgerMetadata {

/**
* 账本的初始化种子;
*
* @return
*/
@DataField(order = 1, primitiveType = PrimitiveType.BYTES)
byte[] getSeed();
/**
* 账本的初始化种子;
*
* @return
*/
@DataField(order = 1, primitiveType = PrimitiveType.BYTES)
byte[] getSeed();

/**
* 共识参与方的默克尔树的根;
*
* @return
*/
@DataField(order = 2, primitiveType = PrimitiveType.BYTES)
HashDigest getParticipantsHash();
/**
* 共识参与方的默克尔树的根;
*
* @return
*/
@DataField(order = 2, primitiveType = PrimitiveType.BYTES)
HashDigest getParticipantsHash();

/**
* 账本配置;
*
* @return
*/
@DataField(order = 3, refContract = true)
LedgerSetting getSetting();
// /**
// * 账本配置;
// *
// * @return
// */
// @DataField(order = 3, refContract = true)
// LedgerSetting getSetting();
/**
* 账本配置的哈希;
*
* @return
*/
@DataField(order = 3, primitiveType = PrimitiveType.BYTES)
HashDigest getSettingsHash();

}

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

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

import com.jd.blockchain.binaryproto.DataContract;
import com.jd.blockchain.binaryproto.DataField;
import com.jd.blockchain.binaryproto.PrimitiveType;
import com.jd.blockchain.consts.DataCodes;
import com.jd.blockchain.crypto.HashDigest;

/**
* {@link LedgerMetadata_V2} 是 {@link LedgerMetadata} 的升级版本,新增加了
* {@link #getPrivilegeHash()} 属性;
*
* @author huanghaiquan
*
*/
@DataContract(code = DataCodes.METADATA, name = "LEDGER-METADATA-V2")
public interface LedgerMetadata_V2 extends LedgerMetadata {

/**
* 加入新的版本;
*
* @return
*/
@DataField(order = 4, primitiveType = PrimitiveType.BYTES)
HashDigest getPrivilegeHash();

}

source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/LedgerSetting.java → source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/LedgerSettings.java View File

@@ -8,7 +8,7 @@ import com.jd.blockchain.ledger.CryptoSetting;
import com.jd.blockchain.utils.Bytes;

@DataContract(code = DataCodes.METADATA_LEDGER_SETTING)
public interface LedgerSetting {
public interface LedgerSettings {

@DataField(order=0, primitiveType=PrimitiveType.TEXT)
String getConsensusProvider();

Loading…
Cancel
Save