@@ -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.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.DataSequenceInfo; | |||
import com.jd.blockchain.statetransfer.callback.DataSequenceReader; | |||
import java.net.InetSocketAddress; | |||
import java.util.LinkedList; | |||
/** | |||
* 数据序列差异的提供者需要使用的回调接口实现类(测试) | |||
* 数据序列差异的提供者需要使用的回调接口实现类 | |||
* @author zhangshuang | |||
* @create 2019/4/22 | |||
* @since 1.0.0 | |||
@@ -57,3 +56,4 @@ public class DataSequenceReaderImpl implements DataSequenceReader { | |||
return null; | |||
} | |||
} | |||
@@ -25,6 +25,6 @@ public interface DataSequenceWriter { | |||
* @param diffContent 需要更新的差异元素 | |||
* @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; | |||
import com.jd.blockchain.statetransfer.DataSequence; | |||
import com.jd.blockchain.statetransfer.DataSequenceElement; | |||
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.utils.codec.Base58Utils; | |||
import org.junit.Before; | |||