@@ -35,7 +35,7 @@ | |||||
+ 3)executions->execution->phase:建议使用package及其后续阶段(若不了解phase含义,请自行查阅相关信息); | + 3)executions->execution->phase:建议使用package及其后续阶段(若不了解phase含义,请自行查阅相关信息); | ||||
+ 4)executions->execution->goals->goal:必须使用compile; | + 4)executions->execution->goals->goal:必须使用compile; | ||||
+ 5)mainClass:必填,该类为需要发布的合约执行类(注意此处是类,不是接口),必须正确配置; | + 5)mainClass:必填,该类为需要发布的合约执行类(注意此处是类,不是接口),必须正确配置; | ||||
+ 6)finalName:必填,最终在编译正常的情况下,会产生{finalName}-jdchain-contract.jar文件,只有该文件是可以发布到JDChain的合约包; | |||||
+ 6)finalName:必填,最终在编译正常的情况下,会产生{finalName}-JDChain-Contract.jar文件,只有该文件是可以发布到JDChain的合约包; | |||||
### 2、执行命令 | ### 2、执行命令 | ||||
@@ -3,7 +3,7 @@ package com.jd.blockchain.gateway.service; | |||||
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.sdk.ContractSettings; | import com.jd.blockchain.sdk.ContractSettings; | ||||
import com.jd.blockchain.sdk.LedgerInitSettings; | |||||
import com.jd.blockchain.sdk.LedgerBaseSettings; | |||||
/** | /** | ||||
* queryService only for gateway; | * queryService only for gateway; | ||||
@@ -34,7 +34,7 @@ public interface GatewayQueryService { | |||||
* 账本Hash | * 账本Hash | ||||
* @return | * @return | ||||
*/ | */ | ||||
LedgerInitSettings getLedgerInitSettings(HashDigest ledgerHash); | |||||
LedgerBaseSettings getLedgerBaseSettings(HashDigest ledgerHash); | |||||
/** | /** | ||||
* 获取账本指定合约信息 | * 获取账本指定合约信息 | ||||
@@ -10,7 +10,7 @@ import com.jd.blockchain.ledger.LedgerAdminInfo; | |||||
import com.jd.blockchain.ledger.LedgerMetadata; | import com.jd.blockchain.ledger.LedgerMetadata; | ||||
import com.jd.blockchain.ledger.ParticipantNode; | import com.jd.blockchain.ledger.ParticipantNode; | ||||
import com.jd.blockchain.sdk.ContractSettings; | import com.jd.blockchain.sdk.ContractSettings; | ||||
import com.jd.blockchain.sdk.LedgerInitSettings; | |||||
import com.jd.blockchain.sdk.LedgerBaseSettings; | |||||
import com.jd.blockchain.utils.QueryUtil; | import com.jd.blockchain.utils.QueryUtil; | ||||
import com.jd.blockchain.utils.codec.HexUtils; | import com.jd.blockchain.utils.codec.HexUtils; | ||||
import com.jd.blockchain.utils.decompiler.utils.DecompilerUtils; | import com.jd.blockchain.utils.decompiler.utils.DecompilerUtils; | ||||
@@ -31,30 +31,26 @@ public class GatewayQueryServiceHandler implements GatewayQueryService { | |||||
@Override | @Override | ||||
public HashDigest[] getLedgersHash(int fromIndex, int count) { | 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; | |||||
HashDigest[] ledgersHashs = peerService.getQueryService().getLedgerHashs(); | |||||
int[] indexAndCount = QueryUtil.calFromIndexAndCount(fromIndex, count, ledgersHashs.length); | |||||
return Arrays.copyOfRange(ledgersHashs, indexAndCount[0], indexAndCount[0] + indexAndCount[1]); | |||||
} | } | ||||
@Override | @Override | ||||
public ParticipantNode[] getConsensusParticipants(HashDigest ledgerHash, int fromIndex, int count) { | 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; | |||||
ParticipantNode[] participantNodes = peerService.getQueryService().getConsensusParticipants(ledgerHash); | |||||
int[] indexAndCount = QueryUtil.calFromIndexAndCount(fromIndex, count, participantNodes.length); | |||||
ParticipantNode[] participantNodesNews = Arrays.copyOfRange(participantNodes, indexAndCount[0], | |||||
indexAndCount[0] + indexAndCount[1]); | |||||
return participantNodesNews; | |||||
} | } | ||||
@Override | @Override | ||||
public LedgerInitSettings getLedgerInitSettings(HashDigest ledgerHash) { | |||||
ParticipantNode[] participantNodes = peerService.getQueryService().getConsensusParticipants(ledgerHash); | |||||
LedgerMetadata ledgerMetadata = peerService.getQueryService().getLedgerMetadata(ledgerHash); | |||||
public LedgerBaseSettings getLedgerBaseSettings(HashDigest ledgerHash) { | |||||
LedgerAdminInfo ledgerAdminInfo = peerService.getQueryService().getLedgerAdminInfo(ledgerHash); | LedgerAdminInfo ledgerAdminInfo = peerService.getQueryService().getLedgerAdminInfo(ledgerHash); | ||||
return initLedgerInitSettings(participantNodes, ledgerMetadata, ledgerAdminInfo); | |||||
return initLedgerBaseSettings(ledgerAdminInfo); | |||||
} | } | ||||
@Override | @Override | ||||
@@ -73,36 +69,38 @@ public class GatewayQueryServiceHandler implements GatewayQueryService { | |||||
} | } | ||||
/** | /** | ||||
* 初始化账本配置 | |||||
* 初始化账本的基本配置 | |||||
* | |||||
* @param ledgerAdminInfo | |||||
* 账本信息 | |||||
* | * | ||||
* @param participantNodes | |||||
* 参与方列表 | |||||
* @param ledgerMetadata | |||||
* 账本元数据 | |||||
* @return | * @return | ||||
*/ | */ | ||||
private LedgerInitSettings initLedgerInitSettings(ParticipantNode[] participantNodes, LedgerMetadata ledgerMetadata, LedgerAdminInfo ledgerAdminInfo) { | |||||
LedgerInitSettings ledgerInitSettings = new LedgerInitSettings(); | |||||
private LedgerBaseSettings initLedgerBaseSettings(LedgerAdminInfo ledgerAdminInfo) { | |||||
LedgerMetadata ledgerMetadata = ledgerAdminInfo.getMetadata(); | |||||
LedgerBaseSettings ledgerBaseSettings = new LedgerBaseSettings(); | |||||
// 设置参与方 | // 设置参与方 | ||||
ledgerInitSettings.setParticipantNodes(participantNodes); | |||||
ledgerBaseSettings.setParticipantNodes(ledgerAdminInfo.getParticipants()); | |||||
// 设置共识设置 | // 设置共识设置 | ||||
ledgerInitSettings.setConsensusSettings(initConsensusSettings(ledgerAdminInfo)); | |||||
ledgerBaseSettings.setConsensusSettings(initConsensusSettings(ledgerAdminInfo)); | |||||
// 设置参与方根Hash | // 设置参与方根Hash | ||||
ledgerInitSettings.setParticipantsHash(ledgerMetadata.getParticipantsHash()); | |||||
ledgerBaseSettings.setParticipantsHash(ledgerMetadata.getParticipantsHash()); | |||||
// 设置算法配置 | // 设置算法配置 | ||||
ledgerInitSettings.setCryptoSetting(ledgerAdminInfo.getSettings().getCryptoSetting()); | |||||
ledgerBaseSettings.setCryptoSetting(ledgerAdminInfo.getSettings().getCryptoSetting()); | |||||
// 设置种子 | // 设置种子 | ||||
ledgerInitSettings.setSeed(initSeed(ledgerMetadata.getSeed())); | |||||
ledgerBaseSettings.setSeed(initSeed(ledgerMetadata.getSeed())); | |||||
// 设置共识协议 | // 设置共识协议 | ||||
ledgerInitSettings.setConsensusProtocol(ledgerAdminInfo.getSettings().getConsensusProvider()); | |||||
ledgerBaseSettings.setConsensusProtocol(ledgerAdminInfo.getSettings().getConsensusProvider()); | |||||
return ledgerInitSettings; | |||||
return ledgerBaseSettings; | |||||
} | } | ||||
/** | /** | ||||
@@ -5,6 +5,8 @@ import java.util.List; | |||||
import javax.servlet.http.HttpServletRequest; | import javax.servlet.http.HttpServletRequest; | ||||
import com.jd.blockchain.gateway.service.GatewayQueryService; | |||||
import com.jd.blockchain.sdk.LedgerBaseSettings; | |||||
import com.jd.blockchain.utils.decompiler.utils.DecompilerUtils; | import com.jd.blockchain.utils.decompiler.utils.DecompilerUtils; | ||||
import org.slf4j.LoggerFactory; | import org.slf4j.LoggerFactory; | ||||
import org.springframework.beans.factory.annotation.Autowired; | import org.springframework.beans.factory.annotation.Autowired; | ||||
@@ -47,6 +49,9 @@ public class BlockBrowserController implements BlockchainExtendQueryService { | |||||
@Autowired | @Autowired | ||||
private PeerService peerService; | private PeerService peerService; | ||||
@Autowired | |||||
private GatewayQueryService gatewayQueryService; | |||||
@Autowired | @Autowired | ||||
private DataRetrievalService dataRetrievalService; | private DataRetrievalService dataRetrievalService; | ||||
@@ -86,10 +91,10 @@ public class BlockBrowserController implements BlockchainExtendQueryService { | |||||
return peerService.getQueryService().getLedgerMetadata(ledgerHash); | return peerService.getQueryService().getLedgerMetadata(ledgerHash); | ||||
} | } | ||||
// @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/settings") | |||||
// public LedgerInitSettings getLedgerInitSettings(@PathVariable(name = "ledgerHash") HashDigest ledgerHash) { | |||||
// return gatewayQueryService.getLedgerInitSettings(ledgerHash); | |||||
// } | |||||
@RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/settings") | |||||
public LedgerBaseSettings getLedgerInitSettings(@PathVariable(name = "ledgerHash") HashDigest ledgerHash) { | |||||
return gatewayQueryService.getLedgerBaseSettings(ledgerHash); | |||||
} | |||||
@RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/blocks") | @RequestMapping(method = RequestMethod.GET, path = "ledgers/{ledgerHash}/blocks") | ||||
public LedgerBlock[] getBlocks(@PathVariable(name = "ledgerHash") HashDigest ledgerHash) { | public LedgerBlock[] getBlocks(@PathVariable(name = "ledgerHash") HashDigest ledgerHash) { | ||||
@@ -0,0 +1,161 @@ | |||||
package com.jd.blockchain.ledger.core; | |||||
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.LedgerMetadata; | |||||
import com.jd.blockchain.ledger.*; | |||||
import com.jd.blockchain.storage.service.ExPolicyKVStorage; | |||||
import com.jd.blockchain.storage.service.VersioningKVStorage; | |||||
import com.jd.blockchain.utils.Bytes; | |||||
import org.slf4j.Logger; | |||||
import org.slf4j.LoggerFactory; | |||||
import static com.jd.blockchain.ledger.core.LedgerAdminDataset.*; | |||||
/** | |||||
* @author shaozhuguang | |||||
* @date 2019-09-16 | |||||
* | |||||
* LedgerAdminInfo的独立实现类,主要用于页面展示,区分 {@link LedgerAdminDataset} | |||||
*/ | |||||
public class LedgerAdminInfoData implements LedgerAdminInfo { | |||||
static { | |||||
DataContractRegistry.register(LedgerMetadata.class); | |||||
DataContractRegistry.register(LedgerMetadata_V2.class); | |||||
} | |||||
private static Logger LOGGER = LoggerFactory.getLogger(LedgerAdminInfoData.class); | |||||
private final Bytes metaPrefix; | |||||
private final Bytes settingPrefix; | |||||
private LedgerMetadata_V2 origMetadata; | |||||
private LedgerAdminDataset.LedgerMetadataInfo metadata; | |||||
/** | |||||
* 原来的账本设置; | |||||
* | |||||
* <br> | |||||
* 对 LedgerMetadata 修改的新配置不能立即生效,需要达成共识后,在下一次区块计算中才生效; | |||||
*/ | |||||
private LedgerSettings previousSettings; | |||||
/** | |||||
* 账本的参与节点; | |||||
*/ | |||||
private ParticipantDataset participants; | |||||
/** | |||||
* 账本参数配置; | |||||
*/ | |||||
private LedgerSettings settings; | |||||
private ExPolicyKVStorage storage; | |||||
public LedgerAdminInfoData(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.origMetadata = loadAndVerifyMetadata(adminAccountHash); | |||||
this.metadata = new LedgerMetadataInfo(origMetadata); | |||||
this.settings = loadAndVerifySettings(metadata.getSettingsHash()); | |||||
// 复制记录一份配置作为上一个区块的原始配置,该实例仅供读取,不做修改,也不会回写到存储; | |||||
this.previousSettings = new LedgerConfiguration(settings); | |||||
String partiPrefix = keyPrefix + LEDGER_PARTICIPANT_PREFIX; | |||||
this.participants = new ParticipantDataset(metadata.getParticipantsHash(), previousSettings.getCryptoSetting(), | |||||
partiPrefix, kvStorage, versioningKVStorage, readonly); | |||||
} | |||||
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 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 Bytes encodeMetadataKey(HashDigest metadataHash) { | |||||
return metaPrefix.concat(metadataHash); | |||||
} | |||||
private LedgerMetadata_V2 deserializeMetadata(byte[] bytes) { | |||||
return BinaryProtocol.decode(bytes); | |||||
} | |||||
private LedgerSettings deserializeSettings(byte[] bytes) { | |||||
return BinaryProtocol.decode(bytes); | |||||
} | |||||
private Bytes encodeSettingsKey(HashDigest settingsHash) { | |||||
return settingPrefix.concat(settingsHash); | |||||
} | |||||
/** | |||||
* 返回元数据配置信息 | |||||
* | |||||
* @return | |||||
*/ | |||||
@Override | |||||
public LedgerMetadata_V2 getMetadata() { | |||||
return metadata; | |||||
} | |||||
/** | |||||
* 返回当前设置的账本配置; | |||||
* | |||||
* @return | |||||
*/ | |||||
@Override | |||||
public LedgerSettings getSettings() { | |||||
return settings; | |||||
} | |||||
/** | |||||
* 返回当前参与方的数量 | |||||
* | |||||
* @return | |||||
*/ | |||||
@Override | |||||
public long getParticipantCount() { | |||||
return participants.getParticipantCount(); | |||||
} | |||||
/** | |||||
* 返回当前参与方列表 | |||||
* | |||||
* @return | |||||
*/ | |||||
@Override | |||||
public ParticipantNode[] getParticipants() { | |||||
return participants.getParticipants(); | |||||
} | |||||
} |
@@ -245,7 +245,7 @@ class LedgerRepositoryImpl implements LedgerRepository { | |||||
@Override | @Override | ||||
public LedgerAdminInfo getAdminInfo() { | public LedgerAdminInfo getAdminInfo() { | ||||
return getAdminSettings(getLatestBlock()); | |||||
return createAdminData(getLatestBlock()); | |||||
} | } | ||||
private LedgerBlock deserialize(byte[] blockBytes) { | private LedgerBlock deserialize(byte[] blockBytes) { | ||||
@@ -267,7 +267,7 @@ class LedgerRepositoryImpl implements LedgerRepository { | |||||
@Override | @Override | ||||
public LedgerAdminInfo getAdminInfo(LedgerBlock block) { | public LedgerAdminInfo getAdminInfo(LedgerBlock block) { | ||||
return getAdminSettings(block); | |||||
return createAdminData(block); | |||||
} | } | ||||
@Override | @Override | ||||
@@ -285,6 +285,17 @@ class LedgerRepositoryImpl implements LedgerRepository { | |||||
return createAdminDataset(block); | return createAdminDataset(block); | ||||
} | } | ||||
/** | |||||
* 生成LedgerAdminInfoData对象 | |||||
* 该对象主要用于页面展示 | |||||
* | |||||
* @param block | |||||
* @return | |||||
*/ | |||||
private LedgerAdminInfoData createAdminData(LedgerBlock block) { | |||||
return new LedgerAdminInfoData(block.getAdminAccountHash(), keyPrefix, exPolicyStorage, versioningStorage, true); | |||||
} | |||||
private LedgerAdminDataset createAdminDataset(LedgerBlock block) { | private LedgerAdminDataset createAdminDataset(LedgerBlock block) { | ||||
return new LedgerAdminDataset(block.getAdminAccountHash(), keyPrefix, exPolicyStorage, versioningStorage, true); | return new LedgerAdminDataset(block.getAdminAccountHash(), keyPrefix, exPolicyStorage, versioningStorage, true); | ||||
} | } | ||||
@@ -14,7 +14,7 @@ import com.jd.blockchain.ledger.ParticipantNode; | |||||
* @since 1.0.0 | * @since 1.0.0 | ||||
* | * | ||||
*/ | */ | ||||
public class LedgerInitSettings { | |||||
public class LedgerBaseSettings { | |||||
/** | /** | ||||
* 账本初始化种子 | * 账本初始化种子 |
@@ -8,6 +8,8 @@ import com.jd.blockchain.transaction.BlockchainQueryService; | |||||
import com.jd.blockchain.utils.http.*; | import com.jd.blockchain.utils.http.*; | ||||
import com.jd.blockchain.utils.web.client.WebResponseConverterFactory; | import com.jd.blockchain.utils.web.client.WebResponseConverterFactory; | ||||
import com.jd.blockchain.sdk.converters.HashDigestToStringConverter; | import com.jd.blockchain.sdk.converters.HashDigestToStringConverter; | ||||
import org.springframework.web.bind.annotation.RequestMapping; | |||||
import org.springframework.web.bind.annotation.RequestMethod; | |||||
/** | /** | ||||
* 作为内部使用的适配接口,用于声明 HTTP 协议的服务请求; | * 作为内部使用的适配接口,用于声明 HTTP 协议的服务请求; | ||||
@@ -194,6 +196,17 @@ public interface HttpBlockchainQueryService extends BlockchainExtendQueryService | |||||
@Override | @Override | ||||
long getAdditionalContractCount(@PathParam(name="ledgerHash", converter=HashDigestToStringConverter.class) HashDigest ledgerHash); | long getAdditionalContractCount(@PathParam(name="ledgerHash", converter=HashDigestToStringConverter.class) HashDigest ledgerHash); | ||||
/** | |||||
* 获取账本信息; | |||||
* | |||||
* @param ledgerHash | |||||
* @return 账本对象;如果不存在,则返回 null; | |||||
*/ | |||||
@HttpAction(method=HttpMethod.GET, path="ledgers/{ledgerHash}/admininfo") | |||||
@Override | |||||
LedgerAdminInfo getLedgerAdminInfo(@PathParam(name="ledgerHash", converter=HashDigestToStringConverter.class) HashDigest ledgerHash); | |||||
/** | /** | ||||
* 返回指定账本的参与列表 | * 返回指定账本的参与列表 | ||||
* | * | ||||
@@ -204,7 +217,6 @@ public interface HttpBlockchainQueryService extends BlockchainExtendQueryService | |||||
@Override | @Override | ||||
ParticipantNode[] getConsensusParticipants(@PathParam(name="ledgerHash", converter=HashDigestToStringConverter.class) HashDigest ledgerHash); | ParticipantNode[] getConsensusParticipants(@PathParam(name="ledgerHash", converter=HashDigestToStringConverter.class) HashDigest ledgerHash); | ||||
/** | /** | ||||
* 返回指定账本的元数据 | * 返回指定账本的元数据 | ||||
* | * | ||||