@@ -1,132 +1,132 @@ | |||||
package com.jd.blockchain.peer.statetransfer; | |||||
import com.jd.blockchain.binaryproto.BinaryEncodingUtils; | |||||
import com.jd.blockchain.crypto.hash.HashDigest; | |||||
import com.jd.blockchain.ledger.LedgerBlock; | |||||
import com.jd.blockchain.ledger.LedgerTransaction; | |||||
import com.jd.blockchain.ledger.core.LedgerManage; | |||||
import com.jd.blockchain.ledger.core.LedgerRepository; | |||||
import com.jd.blockchain.ledger.core.TransactionSet; | |||||
import com.jd.blockchain.statetransfer.DataSequenceElement; | |||||
import com.jd.blockchain.statetransfer.DataSequenceInfo; | |||||
import com.jd.blockchain.statetransfer.callback.DataSequenceReader; | |||||
import com.jd.blockchain.storage.service.DbConnection; | |||||
import com.jd.blockchain.storage.service.DbConnectionFactory; | |||||
import com.jd.blockchain.tools.initializer.LedgerBindingConfig; | |||||
import com.jd.blockchain.utils.codec.Base58Utils; | |||||
import com.jd.blockchain.utils.codec.HexUtils; | |||||
import org.springframework.beans.factory.annotation.Autowired; | |||||
/** | |||||
*数据序列差异的提供者需要使用的回调接口实现类 | |||||
* @author zhangshuang | |||||
* @create 2019/4/11 | |||||
* @since 1.0.0 | |||||
*/ | |||||
public class DataSequenceReaderImpl implements DataSequenceReader { | |||||
private LedgerManage ledgerManager; | |||||
private DbConnectionFactory connFactory; | |||||
private LedgerBindingConfig config; | |||||
public DataSequenceReaderImpl(LedgerBindingConfig config, LedgerManage ledgerManager, DbConnectionFactory connFactory) { | |||||
this.config = config; | |||||
this.ledgerManager = ledgerManager; | |||||
this.connFactory = connFactory; | |||||
} | |||||
/** | |||||
* @param id 账本哈希的Base58编码 | |||||
* @return DataSequenceInfo 数据序列信息 | |||||
*/ | |||||
@Override | |||||
public DataSequenceInfo getDSInfo(String id) { | |||||
byte[] hashBytes = Base58Utils.decode(id); | |||||
HashDigest ledgerHash = new HashDigest(hashBytes); | |||||
LedgerBindingConfig.BindingConfig bindingConfig = config.getLedger(ledgerHash); | |||||
DbConnection dbConnNew = connFactory.connect(bindingConfig.getDbConnection().getUri(), | |||||
bindingConfig.getDbConnection().getPassword()); | |||||
LedgerRepository ledgerRepository = ledgerManager.register(ledgerHash, dbConnNew.getStorageService()); | |||||
return new DataSequenceInfo(id, ledgerRepository.getLatestBlockHeight()); | |||||
} | |||||
/** | |||||
* | |||||
* @param id 账本哈希的Base58编码 | |||||
* @param from 数据序列复制的起始高度 | |||||
* @param to 数据序列复制的结束高度 | |||||
* @return DataSequenceElement【】数据序列差异数据元素的数组 | |||||
*/ | |||||
@Override | |||||
public DataSequenceElement[] getDSDiffContent(String id, long from, long to) { | |||||
DataSequenceElement[] dataSequenceElements = new DataSequenceElement[(int)(to - from + 1)]; | |||||
for (long i = from; i < to + 1; i++) { | |||||
dataSequenceElements[(int)(i - from)] = getDSDiffContent(id, i); | |||||
} | |||||
return dataSequenceElements; | |||||
} | |||||
/** | |||||
* 账本交易序列化 | |||||
* @param transaction 账本交易 | |||||
* @return byte[] 对账本交易进行序列化的结果 | |||||
*/ | |||||
private byte[] serialize(LedgerTransaction transaction) { | |||||
return BinaryEncodingUtils.encode(transaction, LedgerTransaction.class); | |||||
} | |||||
/** | |||||
* 获得账本某一高度区块上的所有交易 | |||||
* @param id 账本哈希的Base58编码 | |||||
* @param height 账本的某个区块高度 | |||||
* @return DataSequenceElement 数据序列差异数据元素 | |||||
*/ | |||||
@Override | |||||
public DataSequenceElement getDSDiffContent(String id, long height) { | |||||
int lastHeightTxTotalNums = 0; | |||||
byte[][] transacionDatas = null; | |||||
byte[] hashBytes = Base58Utils.decode(id); | |||||
HashDigest ledgerHash = new HashDigest(hashBytes); | |||||
LedgerBindingConfig.BindingConfig bindingConfig = config.getLedger(ledgerHash); | |||||
DbConnection dbConnNew = connFactory.connect(bindingConfig.getDbConnection().getUri(), | |||||
bindingConfig.getDbConnection().getPassword()); | |||||
LedgerRepository ledgerRepository = ledgerManager.register(ledgerHash, dbConnNew.getStorageService()); | |||||
LedgerBlock ledgerBlock = ledgerRepository.getBlock(height); | |||||
TransactionSet transactionSet = ledgerRepository.getTransactionSet(ledgerBlock); | |||||
if (height > 0) { | |||||
lastHeightTxTotalNums = (int) ledgerRepository.getTransactionSet(ledgerRepository.getBlock(height - 1)).getTotalCount(); | |||||
} | |||||
int currentHeightTxTotalNums = (int)ledgerRepository.getTransactionSet(ledgerRepository.getBlock(height)).getTotalCount(); | |||||
// get all transactions from current height block | |||||
int currentHeightTxNums = currentHeightTxTotalNums - lastHeightTxTotalNums; | |||||
LedgerTransaction[] transactions = transactionSet.getTxs(lastHeightTxTotalNums , currentHeightTxNums); | |||||
for (int i = 0; i < transactions.length; i++) { | |||||
byte[] transactionData = serialize(transactions[i]); | |||||
transacionDatas[i] = transactionData; | |||||
} | |||||
return new DataSequenceElement(id, height, transacionDatas); | |||||
} | |||||
} | |||||
//package com.jd.blockchain.peer.statetransfer; | |||||
// | |||||
//import com.jd.blockchain.binaryproto.BinaryEncodingUtils; | |||||
//import com.jd.blockchain.crypto.hash.HashDigest; | |||||
//import com.jd.blockchain.ledger.LedgerBlock; | |||||
//import com.jd.blockchain.ledger.LedgerTransaction; | |||||
//import com.jd.blockchain.ledger.core.LedgerManage; | |||||
//import com.jd.blockchain.ledger.core.LedgerRepository; | |||||
//import com.jd.blockchain.ledger.core.TransactionSet; | |||||
//import com.jd.blockchain.statetransfer.DataSequenceElement; | |||||
//import com.jd.blockchain.statetransfer.DataSequenceInfo; | |||||
//import com.jd.blockchain.statetransfer.callback.DataSequenceReader; | |||||
//import com.jd.blockchain.storage.service.DbConnection; | |||||
//import com.jd.blockchain.storage.service.DbConnectionFactory; | |||||
//import com.jd.blockchain.tools.initializer.LedgerBindingConfig; | |||||
//import com.jd.blockchain.utils.codec.Base58Utils; | |||||
//import com.jd.blockchain.utils.codec.HexUtils; | |||||
//import org.springframework.beans.factory.annotation.Autowired; | |||||
// | |||||
///** | |||||
// *数据序列差异的提供者需要使用的回调接口实现类 | |||||
// * @author zhangshuang | |||||
// * @create 2019/4/11 | |||||
// * @since 1.0.0 | |||||
// */ | |||||
//public class DataSequenceReaderImpl implements DataSequenceReader { | |||||
// | |||||
// private LedgerManage ledgerManager; | |||||
// | |||||
// private DbConnectionFactory connFactory; | |||||
// | |||||
// private LedgerBindingConfig config; | |||||
// | |||||
// public DataSequenceReaderImpl(LedgerBindingConfig config, LedgerManage ledgerManager, DbConnectionFactory connFactory) { | |||||
// this.config = config; | |||||
// this.ledgerManager = ledgerManager; | |||||
// this.connFactory = connFactory; | |||||
// } | |||||
// | |||||
// | |||||
// /** | |||||
// * @param id 账本哈希的Base58编码 | |||||
// * @return DataSequenceInfo 数据序列信息 | |||||
// */ | |||||
// @Override | |||||
// public DataSequenceInfo getDSInfo(String id) { | |||||
// | |||||
// byte[] hashBytes = Base58Utils.decode(id); | |||||
// | |||||
// HashDigest ledgerHash = new HashDigest(hashBytes); | |||||
// | |||||
// LedgerBindingConfig.BindingConfig bindingConfig = config.getLedger(ledgerHash); | |||||
// DbConnection dbConnNew = connFactory.connect(bindingConfig.getDbConnection().getUri(), | |||||
// bindingConfig.getDbConnection().getPassword()); | |||||
// LedgerRepository ledgerRepository = ledgerManager.register(ledgerHash, dbConnNew.getStorageService()); | |||||
// | |||||
// return new DataSequenceInfo(id, ledgerRepository.getLatestBlockHeight()); | |||||
// } | |||||
// | |||||
// /** | |||||
// * | |||||
// * @param id 账本哈希的Base58编码 | |||||
// * @param from 数据序列复制的起始高度 | |||||
// * @param to 数据序列复制的结束高度 | |||||
// * @return DataSequenceElement【】数据序列差异数据元素的数组 | |||||
// */ | |||||
// @Override | |||||
// public DataSequenceElement[] getDSDiffContent(String id, long from, long to) { | |||||
// | |||||
// DataSequenceElement[] dataSequenceElements = new DataSequenceElement[(int)(to - from + 1)]; | |||||
// for (long i = from; i < to + 1; i++) { | |||||
// dataSequenceElements[(int)(i - from)] = getDSDiffContent(id, i); | |||||
// } | |||||
// | |||||
// return dataSequenceElements; | |||||
// } | |||||
// | |||||
// /** | |||||
// * 账本交易序列化 | |||||
// * @param transaction 账本交易 | |||||
// * @return byte[] 对账本交易进行序列化的结果 | |||||
// */ | |||||
// private byte[] serialize(LedgerTransaction transaction) { | |||||
// return BinaryEncodingUtils.encode(transaction, LedgerTransaction.class); | |||||
// } | |||||
// | |||||
// /** | |||||
// * 获得账本某一高度区块上的所有交易 | |||||
// * @param id 账本哈希的Base58编码 | |||||
// * @param height 账本的某个区块高度 | |||||
// * @return DataSequenceElement 数据序列差异数据元素 | |||||
// */ | |||||
// @Override | |||||
// public DataSequenceElement getDSDiffContent(String id, long height) { | |||||
// | |||||
// int lastHeightTxTotalNums = 0; | |||||
// | |||||
// byte[][] transacionDatas = null; | |||||
// | |||||
// byte[] hashBytes = Base58Utils.decode(id); | |||||
// | |||||
// HashDigest ledgerHash = new HashDigest(hashBytes); | |||||
// | |||||
// LedgerBindingConfig.BindingConfig bindingConfig = config.getLedger(ledgerHash); | |||||
// DbConnection dbConnNew = connFactory.connect(bindingConfig.getDbConnection().getUri(), | |||||
// bindingConfig.getDbConnection().getPassword()); | |||||
// LedgerRepository ledgerRepository = ledgerManager.register(ledgerHash, dbConnNew.getStorageService()); | |||||
// | |||||
// LedgerBlock ledgerBlock = ledgerRepository.getBlock(height); | |||||
// TransactionSet transactionSet = ledgerRepository.getTransactionSet(ledgerBlock); | |||||
// | |||||
// if (height > 0) { | |||||
// lastHeightTxTotalNums = (int) ledgerRepository.getTransactionSet(ledgerRepository.getBlock(height - 1)).getTotalCount(); | |||||
// } | |||||
// | |||||
// int currentHeightTxTotalNums = (int)ledgerRepository.getTransactionSet(ledgerRepository.getBlock(height)).getTotalCount(); | |||||
// | |||||
// // get all transactions from current height block | |||||
// int currentHeightTxNums = currentHeightTxTotalNums - lastHeightTxTotalNums; | |||||
// | |||||
// LedgerTransaction[] transactions = transactionSet.getTxs(lastHeightTxTotalNums , currentHeightTxNums); | |||||
// | |||||
// for (int i = 0; i < transactions.length; i++) { | |||||
// byte[] transactionData = serialize(transactions[i]); | |||||
// transacionDatas[i] = transactionData; | |||||
// } | |||||
// | |||||
// return new DataSequenceElement(id, height, transacionDatas); | |||||
// } | |||||
// | |||||
// | |||||
//} |
@@ -1,170 +1,170 @@ | |||||
package com.jd.blockchain.peer.statetransfer; | |||||
import com.jd.blockchain.consensus.service.MessageHandle; | |||||
import com.jd.blockchain.ledger.TransactionState; | |||||
import com.jd.blockchain.statetransfer.DataSequenceElement; | |||||
import com.jd.blockchain.statetransfer.DataSequenceInfo; | |||||
import com.jd.blockchain.statetransfer.callback.DataSequenceWriter; | |||||
import com.jd.blockchain.statetransfer.comparator.DataSequenceComparator; | |||||
import java.util.ArrayList; | |||||
import java.util.Collections; | |||||
/** | |||||
*数据序列差异的请求者需要使用的回调接口实现类 | |||||
* @author zhangshuang | |||||
* @create 2019/4/11 | |||||
* @since 1.0.0 | |||||
*/ | |||||
public class DataSequenceWriterImpl implements DataSequenceWriter { | |||||
private long currHeight; | |||||
private ArrayList<DataSequenceElement> deceidedElements = new ArrayList<DataSequenceElement>(); | |||||
private MessageHandle batchMessageHandle; | |||||
public DataSequenceWriterImpl(MessageHandle batchMessageHandle) { | |||||
this.batchMessageHandle = batchMessageHandle; | |||||
} | |||||
/** | |||||
* 检查数据序列差异元素中的高度是否合理; | |||||
* @param currHeight 当前结点的账本高度 | |||||
* @param dsUpdateElements 需要更新到本地结点的数据序列元素List | |||||
* @return | |||||
*/ | |||||
private int checkElementsHeight(long currHeight, ArrayList<DataSequenceElement> dsUpdateElements) { | |||||
boolean lossMiddleElements = false; | |||||
// lose first element | |||||
if (currHeight + 1 < dsUpdateElements.get(0).getHeight()){ | |||||
System.out.println("Diff response loss first element error!"); | |||||
return DataSequenceErrorType.DATA_SEQUENCE_LOSS_FIRST_ELEMENT.CODE; | |||||
} | |||||
else { | |||||
for (int i = 0; i < dsUpdateElements.size(); i++) { | |||||
if (dsUpdateElements.get(i).getHeight() == currHeight + 1 + i) { | |||||
deceidedElements.add(dsUpdateElements.get(i)); | |||||
} | |||||
// lose middle elements | |||||
else { | |||||
lossMiddleElements = true; | |||||
break; | |||||
} | |||||
} | |||||
if (lossMiddleElements) { | |||||
System.out.println("Diff response loss middle elements error!"); | |||||
return DataSequenceErrorType.DATA_SEQUENCE_LOSS_MIDDLE_ELEMENT.CODE; | |||||
} | |||||
System.out.println("Diff response elements height normal!"); | |||||
return DataSequenceErrorType.DATA_SEQUENCE_ELEMENT_HEIGHT_NORMAL.CODE; | |||||
} | |||||
} | |||||
/** | |||||
* 对本地结点执行账本更新 | |||||
* @param realmName 账本哈希的Base58编码 | |||||
* @return void | |||||
*/ | |||||
private void exeUpdate(String realmName) { | |||||
for (int i = 0; i < deceidedElements.size(); i++) { | |||||
byte[][] element = deceidedElements.get(i).getData(); | |||||
String batchId = batchMessageHandle.beginBatch(realmName); | |||||
try { | |||||
int msgId = 0; | |||||
for (byte[] txContent : element) { | |||||
batchMessageHandle.processOrdered(msgId++, txContent, realmName, batchId); | |||||
} | |||||
// 结块 | |||||
batchMessageHandle.completeBatch(realmName, batchId); | |||||
batchMessageHandle.commitBatch(realmName, batchId); | |||||
} catch (Exception e) { | |||||
// todo 需要处理应答码 404 | |||||
batchMessageHandle.rollbackBatch(realmName, batchId, TransactionState.DATA_SEQUENCE_UPDATE_ERROR.CODE); | |||||
} | |||||
} | |||||
} | |||||
/** | |||||
* @param dsInfo 当前结点的数据序列信息 | |||||
* @param diffContents 数据序列差异的数据元素数组 | |||||
* @return int 更新结果码 | |||||
*/ | |||||
@Override | |||||
public int updateDSInfo(DataSequenceInfo dsInfo, DataSequenceElement[] diffContents) { | |||||
int result = 0; | |||||
try { | |||||
ArrayList<DataSequenceElement> dsUpdateElements = new ArrayList<DataSequenceElement>(); | |||||
//remove unexpected elements | |||||
for (int i = 0 ; i < diffContents.length; i++) { | |||||
if (diffContents[i].getId().equals(dsInfo.getId())) { | |||||
dsUpdateElements.add(diffContents[i]); | |||||
} | |||||
} | |||||
// sort elements by height | |||||
Collections.sort(dsUpdateElements, new DataSequenceComparator()); | |||||
currHeight = dsInfo.getHeight(); | |||||
// check element's height | |||||
result = checkElementsHeight(currHeight, dsUpdateElements); | |||||
// cann't exe update | |||||
if (result == DataSequenceErrorType.DATA_SEQUENCE_LOSS_FIRST_ELEMENT.CODE) { | |||||
return result; | |||||
} | |||||
// exe elements update | |||||
else { | |||||
exeUpdate(dsInfo.getId()); | |||||
return result; | |||||
} | |||||
} catch (Exception e) { | |||||
System.out.println(e.getMessage()); | |||||
e.printStackTrace(); | |||||
} | |||||
return result; | |||||
} | |||||
@Override | |||||
public int updateDSInfo(DataSequenceInfo dsInfo, DataSequenceElement diffContents) { | |||||
return 0; | |||||
} | |||||
/** | |||||
* 数据序列更新错误码 | |||||
* @param | |||||
* @return | |||||
*/ | |||||
public enum DataSequenceErrorType { | |||||
DATA_SEQUENCE_LOSS_FIRST_ELEMENT((byte) 0x1), | |||||
DATA_SEQUENCE_LOSS_MIDDLE_ELEMENT((byte) 0x2), | |||||
DATA_SEQUENCE_ELEMENT_HEIGHT_NORMAL((byte) 0x3), | |||||
; | |||||
public final int CODE; | |||||
private DataSequenceErrorType(byte code) { | |||||
this.CODE = code; | |||||
} | |||||
public static DataSequenceErrorType valueOf(byte code) { | |||||
for (DataSequenceErrorType errorType : DataSequenceErrorType.values()) { | |||||
if (errorType.CODE == code) { | |||||
return errorType; | |||||
} | |||||
} | |||||
throw new IllegalArgumentException("Unsupported code[" + code + "] of errorType!"); | |||||
} | |||||
} | |||||
} | |||||
//package com.jd.blockchain.peer.statetransfer; | |||||
// | |||||
//import com.jd.blockchain.consensus.service.MessageHandle; | |||||
//import com.jd.blockchain.ledger.TransactionState; | |||||
//import com.jd.blockchain.statetransfer.DataSequenceElement; | |||||
//import com.jd.blockchain.statetransfer.DataSequenceInfo; | |||||
//import com.jd.blockchain.statetransfer.callback.DataSequenceWriter; | |||||
//import com.jd.blockchain.statetransfer.comparator.DataSequenceComparator; | |||||
// | |||||
//import java.util.ArrayList; | |||||
//import java.util.Collections; | |||||
// | |||||
///** | |||||
// *数据序列差异的请求者需要使用的回调接口实现类 | |||||
// * @author zhangshuang | |||||
// * @create 2019/4/11 | |||||
// * @since 1.0.0 | |||||
// */ | |||||
//public class DataSequenceWriterImpl implements DataSequenceWriter { | |||||
// | |||||
// private long currHeight; | |||||
// private ArrayList<DataSequenceElement> deceidedElements = new ArrayList<DataSequenceElement>(); | |||||
// | |||||
// private MessageHandle batchMessageHandle; | |||||
// | |||||
// | |||||
// public DataSequenceWriterImpl(MessageHandle batchMessageHandle) { | |||||
// this.batchMessageHandle = batchMessageHandle; | |||||
// } | |||||
// | |||||
// /** | |||||
// * 检查数据序列差异元素中的高度是否合理; | |||||
// * @param currHeight 当前结点的账本高度 | |||||
// * @param dsUpdateElements 需要更新到本地结点的数据序列元素List | |||||
// * @return | |||||
// */ | |||||
// private int checkElementsHeight(long currHeight, ArrayList<DataSequenceElement> dsUpdateElements) { | |||||
// boolean lossMiddleElements = false; | |||||
// | |||||
// // lose first element | |||||
// if (currHeight + 1 < dsUpdateElements.get(0).getHeight()){ | |||||
// System.out.println("Diff response loss first element error!"); | |||||
// return DataSequenceErrorType.DATA_SEQUENCE_LOSS_FIRST_ELEMENT.CODE; | |||||
// } | |||||
// else { | |||||
// for (int i = 0; i < dsUpdateElements.size(); i++) { | |||||
// if (dsUpdateElements.get(i).getHeight() == currHeight + 1 + i) { | |||||
// deceidedElements.add(dsUpdateElements.get(i)); | |||||
// } | |||||
// // lose middle elements | |||||
// else { | |||||
// lossMiddleElements = true; | |||||
// break; | |||||
// } | |||||
// } | |||||
// | |||||
// if (lossMiddleElements) { | |||||
// System.out.println("Diff response loss middle elements error!"); | |||||
// return DataSequenceErrorType.DATA_SEQUENCE_LOSS_MIDDLE_ELEMENT.CODE; | |||||
// } | |||||
// | |||||
// System.out.println("Diff response elements height normal!"); | |||||
// return DataSequenceErrorType.DATA_SEQUENCE_ELEMENT_HEIGHT_NORMAL.CODE; | |||||
// } | |||||
// | |||||
// } | |||||
// | |||||
// /** | |||||
// * 对本地结点执行账本更新 | |||||
// * @param realmName 账本哈希的Base58编码 | |||||
// * @return void | |||||
// */ | |||||
// private void exeUpdate(String realmName) { | |||||
// | |||||
// for (int i = 0; i < deceidedElements.size(); i++) { | |||||
// byte[][] element = deceidedElements.get(i).getData(); | |||||
// | |||||
// String batchId = batchMessageHandle.beginBatch(realmName); | |||||
// try { | |||||
// int msgId = 0; | |||||
// for (byte[] txContent : element) { | |||||
// batchMessageHandle.processOrdered(msgId++, txContent, realmName, batchId); | |||||
// } | |||||
// // 结块 | |||||
// batchMessageHandle.completeBatch(realmName, batchId); | |||||
// batchMessageHandle.commitBatch(realmName, batchId); | |||||
// } catch (Exception e) { | |||||
// // todo 需要处理应答码 404 | |||||
// batchMessageHandle.rollbackBatch(realmName, batchId, TransactionState.DATA_SEQUENCE_UPDATE_ERROR.CODE); | |||||
// } | |||||
// } | |||||
// | |||||
// } | |||||
// | |||||
// /** | |||||
// * @param dsInfo 当前结点的数据序列信息 | |||||
// * @param diffContents 数据序列差异的数据元素数组 | |||||
// * @return int 更新结果码 | |||||
// */ | |||||
// @Override | |||||
// public int updateDSInfo(DataSequenceInfo dsInfo, DataSequenceElement[] diffContents) { | |||||
// int result = 0; | |||||
// | |||||
// try { | |||||
// ArrayList<DataSequenceElement> dsUpdateElements = new ArrayList<DataSequenceElement>(); | |||||
// //remove unexpected elements | |||||
// for (int i = 0 ; i < diffContents.length; i++) { | |||||
// if (diffContents[i].getId().equals(dsInfo.getId())) { | |||||
// dsUpdateElements.add(diffContents[i]); | |||||
// } | |||||
// } | |||||
// | |||||
// // sort elements by height | |||||
// Collections.sort(dsUpdateElements, new DataSequenceComparator()); | |||||
// | |||||
// currHeight = dsInfo.getHeight(); | |||||
// | |||||
// // check element's height | |||||
// result = checkElementsHeight(currHeight, dsUpdateElements); | |||||
// | |||||
// // cann't exe update | |||||
// if (result == DataSequenceErrorType.DATA_SEQUENCE_LOSS_FIRST_ELEMENT.CODE) { | |||||
// return result; | |||||
// } | |||||
// // exe elements update | |||||
// else { | |||||
// exeUpdate(dsInfo.getId()); | |||||
// return result; | |||||
// } | |||||
// } catch (Exception e) { | |||||
// System.out.println(e.getMessage()); | |||||
// e.printStackTrace(); | |||||
// } | |||||
// | |||||
// return result; | |||||
// } | |||||
// | |||||
// @Override | |||||
// public int updateDSInfo(DataSequenceInfo dsInfo, DataSequenceElement diffContents) { | |||||
// return 0; | |||||
// } | |||||
// | |||||
// | |||||
// /** | |||||
// * 数据序列更新错误码 | |||||
// * @param | |||||
// * @return | |||||
// */ | |||||
// public enum DataSequenceErrorType { | |||||
// DATA_SEQUENCE_LOSS_FIRST_ELEMENT((byte) 0x1), | |||||
// DATA_SEQUENCE_LOSS_MIDDLE_ELEMENT((byte) 0x2), | |||||
// DATA_SEQUENCE_ELEMENT_HEIGHT_NORMAL((byte) 0x3), | |||||
// ; | |||||
// public final int CODE; | |||||
// | |||||
// private DataSequenceErrorType(byte code) { | |||||
// this.CODE = code; | |||||
// } | |||||
// | |||||
// public static DataSequenceErrorType valueOf(byte code) { | |||||
// for (DataSequenceErrorType errorType : DataSequenceErrorType.values()) { | |||||
// if (errorType.CODE == code) { | |||||
// return errorType; | |||||
// } | |||||
// } | |||||
// throw new IllegalArgumentException("Unsupported code[" + code + "] of errorType!"); | |||||
// } | |||||
// } | |||||
// | |||||
//} |
@@ -1,7 +1,4 @@ | |||||
package test.com.jd.blockchain.statetransfer; | |||||
import com.jd.blockchain.statetransfer.DataSequenceElement; | |||||
import com.jd.blockchain.statetransfer.DataSequenceInfo; | |||||
package com.jd.blockchain.statetransfer; | |||||
import java.net.InetSocketAddress; | import java.net.InetSocketAddress; | ||||
import java.util.LinkedList; | import java.util.LinkedList; |
@@ -1,14 +1,13 @@ | |||||
package test.com.jd.blockchain.statetransfer; | |||||
package com.jd.blockchain.statetransfer.callback; | |||||
import com.jd.blockchain.statetransfer.DataSequence; | |||||
import com.jd.blockchain.statetransfer.DataSequenceElement; | import com.jd.blockchain.statetransfer.DataSequenceElement; | ||||
import com.jd.blockchain.statetransfer.DataSequenceInfo; | import com.jd.blockchain.statetransfer.DataSequenceInfo; | ||||
import com.jd.blockchain.statetransfer.callback.DataSequenceReader; | |||||
import java.net.InetSocketAddress; | |||||
import java.util.LinkedList; | import java.util.LinkedList; | ||||
/** | /** | ||||
* 数据序列差异的提供者需要使用的回调接口实现类(测试) | |||||
* 数据序列差异的提供者需要使用的回调接口实现类 | |||||
* @author zhangshuang | * @author zhangshuang | ||||
* @create 2019/4/22 | * @create 2019/4/22 | ||||
* @since 1.0.0 | * @since 1.0.0 | ||||
@@ -57,3 +56,4 @@ public class DataSequenceReaderImpl implements DataSequenceReader { | |||||
return null; | return null; | ||||
} | } | ||||
} | } | ||||
@@ -25,6 +25,6 @@ public interface DataSequenceWriter { | |||||
* @param diffContent 需要更新的差异元素 | * @param diffContent 需要更新的差异元素 | ||||
* @return 更新结果编码 | * @return 更新结果编码 | ||||
*/ | */ | ||||
int updateDSInfo(DataSequenceInfo dsInfo, DataSequenceElement diffContent); | |||||
// int updateDSInfo(DataSequenceInfo dsInfo, DataSequenceElement diffContent); | |||||
} | } |
@@ -0,0 +1,142 @@ | |||||
package com.jd.blockchain.statetransfer.callback; | |||||
import com.jd.blockchain.statetransfer.DataSequence; | |||||
import com.jd.blockchain.statetransfer.DataSequenceElement; | |||||
import com.jd.blockchain.statetransfer.DataSequenceInfo; | |||||
import java.util.ArrayList; | |||||
/** | |||||
* 数据序列差异的请求者需要使用的回调接口实现类 | |||||
* @author zhangshuang | |||||
* @create 2019/4/22 | |||||
* @since 1.0.0 | |||||
*/ | |||||
public class DataSequenceWriterImpl implements DataSequenceWriter { | |||||
private long currHeight; | |||||
private DataSequence currDataSequence; | |||||
private ArrayList<DataSequenceElement> deceidedElements = new ArrayList<DataSequenceElement>(); | |||||
public DataSequenceWriterImpl(DataSequence currDataSequence) { | |||||
this.currDataSequence = currDataSequence; | |||||
} | |||||
/** | |||||
* 检查数据序列差异元素中的高度是否合理; | |||||
* @param currHeight 当前结点的账本高度 | |||||
* @param dsUpdateElements 需要更新到本地结点的数据序列元素List | |||||
* @return | |||||
*/ | |||||
private int checkElementsHeight(long currHeight, ArrayList<DataSequenceElement> dsUpdateElements) { | |||||
boolean lossMiddleElements = false; | |||||
// lose first element | |||||
if (currHeight + 1 < dsUpdateElements.get(0).getHeight()){ | |||||
System.out.println("Diff response loss first element error!"); | |||||
return DataSequenceErrorType.DATA_SEQUENCE_LOSS_FIRST_ELEMENT.CODE; | |||||
} | |||||
else { | |||||
for (int i = 0; i < dsUpdateElements.size(); i++) { | |||||
if (dsUpdateElements.get(i).getHeight() == currHeight + 1 + i) { | |||||
deceidedElements.add(dsUpdateElements.get(i)); | |||||
} | |||||
// lose middle elements | |||||
else { | |||||
lossMiddleElements = true; | |||||
break; | |||||
} | |||||
} | |||||
if (lossMiddleElements) { | |||||
System.out.println("Diff response loss middle elements error!"); | |||||
return DataSequenceErrorType.DATA_SEQUENCE_LOSS_MIDDLE_ELEMENT.CODE; | |||||
} | |||||
System.out.println("Diff response elements height normal!"); | |||||
return DataSequenceErrorType.DATA_SEQUENCE_ELEMENT_HEIGHT_NORMAL.CODE; | |||||
} | |||||
} | |||||
@Override | |||||
public int updateDSInfo(DataSequenceInfo dsInfo, DataSequenceElement[] diffContents) { | |||||
int result = 0; | |||||
try { | |||||
ArrayList<DataSequenceElement> dsUpdateElements = new ArrayList<DataSequenceElement>(); | |||||
if (diffContents == null) { | |||||
throw new IllegalArgumentException("Update diffContents is null!"); | |||||
} | |||||
//remove unexpected elements | |||||
for (int i = 0 ; i < diffContents.length; i++) { | |||||
if (diffContents[i].getId().equals(dsInfo.getId())) { | |||||
dsUpdateElements.add(diffContents[i]); | |||||
} | |||||
} | |||||
currHeight = dsInfo.getHeight(); | |||||
// check element's height | |||||
result = checkElementsHeight(currHeight, dsUpdateElements); | |||||
// cann't exe update | |||||
if (result == DataSequenceErrorType.DATA_SEQUENCE_LOSS_FIRST_ELEMENT.CODE) { | |||||
return result; | |||||
} | |||||
// exe elements update | |||||
else { | |||||
System.out.println("Old data sequence state: "); | |||||
System.out.println(" Current height = " + currDataSequence.getDataSequenceElements().getLast().getHeight()); | |||||
currDataSequence.addElements(deceidedElements.toArray(new DataSequenceElement[deceidedElements.size()])); | |||||
System.out.println("Update diffContents is completed!"); | |||||
System.out.println("New data sequence state: "); | |||||
System.out.println(" Current height = " + currDataSequence.getDataSequenceElements().getLast().getHeight()); | |||||
return result; | |||||
} | |||||
} catch (Exception e) { | |||||
System.out.println(e.getMessage()); | |||||
e.printStackTrace(); | |||||
} | |||||
return DataSequenceErrorType.DATA_SEQUENCE_ELEMENT_HEIGHT_NORMAL.CODE; | |||||
} | |||||
// @Override | |||||
// public int updateDSInfo(DataSequenceInfo dsInfo, DataSequenceElement diffContent) { | |||||
// currDataSequence.addElement(diffContent); | |||||
// return DataSequenceErrorType.DATA_SEQUENCE_ELEMENT_HEIGHT_NORMAL.CODE; | |||||
// } | |||||
public enum DataSequenceErrorType { | |||||
DATA_SEQUENCE_LOSS_FIRST_ELEMENT((byte) 0x1), | |||||
DATA_SEQUENCE_LOSS_MIDDLE_ELEMENT((byte) 0x2), | |||||
DATA_SEQUENCE_ELEMENT_HEIGHT_NORMAL((byte) 0x3), | |||||
; | |||||
public final int CODE; | |||||
private DataSequenceErrorType(byte code) { | |||||
this.CODE = code; | |||||
} | |||||
public static DataSequenceErrorType valueOf(byte code) { | |||||
for (DataSequenceErrorType errorType : DataSequenceErrorType.values()) { | |||||
if (errorType.CODE == code) { | |||||
return errorType; | |||||
} | |||||
} | |||||
throw new IllegalArgumentException("Unsupported code[" + code + "] of errorType!"); | |||||
} | |||||
} | |||||
} | |||||
@@ -1,68 +0,0 @@ | |||||
package test.com.jd.blockchain.statetransfer; | |||||
import com.jd.blockchain.statetransfer.DataSequenceElement; | |||||
import com.jd.blockchain.statetransfer.DataSequenceInfo; | |||||
import com.jd.blockchain.statetransfer.callback.DataSequenceWriter; | |||||
/** | |||||
* 数据序列差异的请求者需要使用的回调接口实现类(测试) | |||||
* @author zhangshuang | |||||
* @create 2019/4/22 | |||||
* @since 1.0.0 | |||||
*/ | |||||
public class DataSequenceWriterImpl implements DataSequenceWriter { | |||||
DataSequence currDataSequence; | |||||
public DataSequenceWriterImpl(DataSequence currDataSequence) { | |||||
this.currDataSequence = currDataSequence; | |||||
} | |||||
@Override | |||||
public int updateDSInfo(DataSequenceInfo dsInfo, DataSequenceElement[] diffContents) { | |||||
if (diffContents == null) { | |||||
throw new IllegalArgumentException("Update diffContents is null!"); | |||||
} | |||||
System.out.println("Old data sequence state: "); | |||||
System.out.println(" Current height = " + currDataSequence.getDataSequenceElements().getLast().getHeight()); | |||||
currDataSequence.addElements(diffContents); | |||||
System.out.println("Update diffContents is completed!"); | |||||
System.out.println("New data sequence state: "); | |||||
System.out.println(" Current height = " + currDataSequence.getDataSequenceElements().getLast().getHeight()); | |||||
return DataSequenceErrorType.DATA_SEQUENCE_ELEMENT_HEIGHT_NORMAL.CODE; | |||||
} | |||||
@Override | |||||
public int updateDSInfo(DataSequenceInfo id, DataSequenceElement diffContent) { | |||||
currDataSequence.addElement(diffContent); | |||||
return DataSequenceErrorType.DATA_SEQUENCE_ELEMENT_HEIGHT_NORMAL.CODE; | |||||
} | |||||
public enum DataSequenceErrorType { | |||||
DATA_SEQUENCE_LOSS_FIRST_ELEMENT((byte) 0x1), | |||||
DATA_SEQUENCE_LOSS_MIDDLE_ELEMENT((byte) 0x2), | |||||
DATA_SEQUENCE_ELEMENT_HEIGHT_NORMAL((byte) 0x3), | |||||
; | |||||
public final int CODE; | |||||
private DataSequenceErrorType(byte code) { | |||||
this.CODE = code; | |||||
} | |||||
public static DataSequenceErrorType valueOf(byte code) { | |||||
for (DataSequenceErrorType errorType : DataSequenceErrorType.values()) { | |||||
if (errorType.CODE == code) { | |||||
return errorType; | |||||
} | |||||
} | |||||
throw new IllegalArgumentException("Unsupported code[" + code + "] of errorType!"); | |||||
} | |||||
} | |||||
} |
@@ -1,7 +1,10 @@ | |||||
package test.com.jd.blockchain.statetransfer; | package test.com.jd.blockchain.statetransfer; | ||||
import com.jd.blockchain.statetransfer.DataSequence; | |||||
import com.jd.blockchain.statetransfer.DataSequenceElement; | import com.jd.blockchain.statetransfer.DataSequenceElement; | ||||
import com.jd.blockchain.statetransfer.DataSequenceInfo; | import com.jd.blockchain.statetransfer.DataSequenceInfo; | ||||
import com.jd.blockchain.statetransfer.callback.DataSequenceReaderImpl; | |||||
import com.jd.blockchain.statetransfer.callback.DataSequenceWriterImpl; | |||||
import com.jd.blockchain.statetransfer.process.DSProcessManager; | import com.jd.blockchain.statetransfer.process.DSProcessManager; | ||||
import com.jd.blockchain.utils.codec.Base58Utils; | import com.jd.blockchain.utils.codec.Base58Utils; | ||||
import org.junit.Before; | import org.junit.Before; | ||||