Browse Source

adjustment code

tags/1.0.0
zhangshuang 5 years ago
parent
commit
9a6a9e4fd1
8 changed files with 453 additions and 379 deletions
  1. +132
    -132
      source/peer/src/main/java/com/jd/blockchain/peer/statetransfer/DataSequenceReaderImpl.java
  2. +170
    -170
      source/peer/src/main/java/com/jd/blockchain/peer/statetransfer/DataSequenceWriterImpl.java
  3. +1
    -4
      source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/DataSequence.java
  4. +4
    -4
      source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/callback/DataSequenceReaderImpl.java
  5. +1
    -1
      source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/callback/DataSequenceWriter.java
  6. +142
    -0
      source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/callback/DataSequenceWriterImpl.java
  7. +0
    -68
      source/state-transfer/src/test/java/test/com/jd/blockchain/statetransfer/DataSequenceWriterImpl.java
  8. +3
    -0
      source/state-transfer/src/test/java/test/com/jd/blockchain/statetransfer/StateTransferLayerTest.java

+ 132
- 132
source/peer/src/main/java/com/jd/blockchain/peer/statetransfer/DataSequenceReaderImpl.java View File

@@ -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);
// }
//
//
//}

+ 170
- 170
source/peer/src/main/java/com/jd/blockchain/peer/statetransfer/DataSequenceWriterImpl.java View File

@@ -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!");
// }
// }
//
//}

source/state-transfer/src/test/java/test/com/jd/blockchain/statetransfer/DataSequence.java → source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/DataSequence.java View File

@@ -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;

source/state-transfer/src/test/java/test/com/jd/blockchain/statetransfer/DataSequenceReaderImpl.java → source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/callback/DataSequenceReaderImpl.java View File

@@ -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;
}
}


+ 1
- 1
source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/callback/DataSequenceWriter.java View File

@@ -25,6 +25,6 @@ public interface DataSequenceWriter {
* @param diffContent 需要更新的差异元素
* @return 更新结果编码
*/
int updateDSInfo(DataSequenceInfo dsInfo, DataSequenceElement diffContent);
// int updateDSInfo(DataSequenceInfo dsInfo, DataSequenceElement diffContent);

}

+ 142
- 0
source/state-transfer/src/main/java/com/jd/blockchain/statetransfer/callback/DataSequenceWriterImpl.java View File

@@ -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!");
}
}

}


+ 0
- 68
source/state-transfer/src/test/java/test/com/jd/blockchain/statetransfer/DataSequenceWriterImpl.java View File

@@ -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!");
}
}

}

+ 3
- 0
source/state-transfer/src/test/java/test/com/jd/blockchain/statetransfer/StateTransferLayerTest.java View File

@@ -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;


Loading…
Cancel
Save