@@ -35,7 +35,7 @@ | |||
+ 3)executions->execution->phase:建议使用package及其后续阶段(若不了解phase含义,请自行查阅相关信息); | |||
+ 4)executions->execution->goals->goal:必须使用compile; | |||
+ 5)mainClass:必填,该类为需要发布的合约执行类(注意此处是类,不是接口),必须正确配置; | |||
+ 6)finalName:必填,最终在编译正常的情况下,会产生{finalName}-jdchain-contract.jar文件,只有该文件是可以发布到JDChain的合约包; | |||
+ 6)finalName:必填,最终在编译正常的情况下,会产生{finalName}-JDChain-Contract.jar文件,只有该文件是可以发布到JDChain的合约包; | |||
### 2、执行命令 | |||
@@ -3,7 +3,7 @@ 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.sdk.LedgerBaseSettings; | |||
/** | |||
* queryService only for gateway; | |||
@@ -34,7 +34,7 @@ public interface GatewayQueryService { | |||
* 账本Hash | |||
* @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.ParticipantNode; | |||
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.codec.HexUtils; | |||
import com.jd.blockchain.utils.decompiler.utils.DecompilerUtils; | |||
@@ -31,30 +31,26 @@ public class GatewayQueryServiceHandler implements GatewayQueryService { | |||
@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; | |||
HashDigest[] ledgersHashs = peerService.getQueryService().getLedgerHashs(); | |||
int[] indexAndCount = QueryUtil.calFromIndexAndCount(fromIndex, count, ledgersHashs.length); | |||
return Arrays.copyOfRange(ledgersHashs, indexAndCount[0], indexAndCount[0] + indexAndCount[1]); | |||
} | |||
@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; | |||
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 | |||
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); | |||
return initLedgerInitSettings(participantNodes, ledgerMetadata, ledgerAdminInfo); | |||
return initLedgerBaseSettings(ledgerAdminInfo); | |||
} | |||
@Override | |||
@@ -73,36 +69,38 @@ public class GatewayQueryServiceHandler implements GatewayQueryService { | |||
} | |||
/** | |||
* 初始化账本配置 | |||
* 初始化账本的基本配置 | |||
* | |||
* @param ledgerAdminInfo | |||
* 账本信息 | |||
* | |||
* @param participantNodes | |||
* 参与方列表 | |||
* @param ledgerMetadata | |||
* 账本元数据 | |||
* @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 | |||
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 com.jd.blockchain.gateway.service.GatewayQueryService; | |||
import com.jd.blockchain.sdk.LedgerBaseSettings; | |||
import com.jd.blockchain.utils.decompiler.utils.DecompilerUtils; | |||
import org.slf4j.LoggerFactory; | |||
import org.springframework.beans.factory.annotation.Autowired; | |||
@@ -47,6 +49,9 @@ public class BlockBrowserController implements BlockchainExtendQueryService { | |||
@Autowired | |||
private PeerService peerService; | |||
@Autowired | |||
private GatewayQueryService gatewayQueryService; | |||
@Autowired | |||
private DataRetrievalService dataRetrievalService; | |||
@@ -86,10 +91,10 @@ public class BlockBrowserController implements BlockchainExtendQueryService { | |||
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") | |||
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 | |||
public LedgerAdminInfo getAdminInfo() { | |||
return getAdminSettings(getLatestBlock()); | |||
return createAdminData(getLatestBlock()); | |||
} | |||
private LedgerBlock deserialize(byte[] blockBytes) { | |||
@@ -267,7 +267,7 @@ class LedgerRepositoryImpl implements LedgerRepository { | |||
@Override | |||
public LedgerAdminInfo getAdminInfo(LedgerBlock block) { | |||
return getAdminSettings(block); | |||
return createAdminData(block); | |||
} | |||
@Override | |||
@@ -285,6 +285,17 @@ class LedgerRepositoryImpl implements LedgerRepository { | |||
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) { | |||
return new LedgerAdminDataset(block.getAdminAccountHash(), keyPrefix, exPolicyStorage, versioningStorage, true); | |||
} | |||
@@ -14,7 +14,7 @@ import com.jd.blockchain.ledger.ParticipantNode; | |||
* @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.web.client.WebResponseConverterFactory; | |||
import com.jd.blockchain.sdk.converters.HashDigestToStringConverter; | |||
import org.springframework.web.bind.annotation.RequestMapping; | |||
import org.springframework.web.bind.annotation.RequestMethod; | |||
/** | |||
* 作为内部使用的适配接口,用于声明 HTTP 协议的服务请求; | |||
@@ -194,6 +196,17 @@ public interface HttpBlockchainQueryService extends BlockchainExtendQueryService | |||
@Override | |||
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 | |||
ParticipantNode[] getConsensusParticipants(@PathParam(name="ledgerHash", converter=HashDigestToStringConverter.class) HashDigest ledgerHash); | |||
/** | |||
* 返回指定账本的元数据 | |||
* | |||