com.jd.blockchain.transaction.TxRequestMessage Maven / Gradle / Ivy
package com.jd.blockchain.transaction;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import com.jd.binaryproto.DataContractRegistry;
import com.jd.blockchain.crypto.AddressEncoding;
import com.jd.blockchain.crypto.HashDigest;
import com.jd.blockchain.ledger.BlockchainIdentity;
import com.jd.blockchain.ledger.DigitalSignature;
import com.jd.blockchain.ledger.MagicNumber;
import com.jd.blockchain.ledger.TransactionContent;
import com.jd.blockchain.ledger.TransactionRequest;
import utils.Bytes;
/**
* TxRequestMessage 交易消息;
*
*
* TxRequestMessage 表示参与者提交的交易请求,由3部分组成:交易内容、参与者签名、网关节点签名;
*
*
* 字节位如下:
* [第1字节]:标识数据类型为交易请求的魔数常量 ({@link MagicNumber#TX_REQUEST});
*
* [第2字节] - [第N字节]: 交易内容;
*
* [第N+1字节]: 交易参与者数量(有效值范围 0 - 255);
* 注:在单个交易中,参与者的数量总是有限的,对于那些需要更多参与者且数量不确定的场景,可以通过合约来实现把参与者分为多次 TX 提交,最终组合完成一次完整的业务进程;
* [第N+2字节] - [第X字节]: 参与者的签名列表;
*
* [第X+1字节]:对交易请求的哈希算法的代码;
* [第X+2字节] - [第Y字节]:对交易请求的哈希值;针对交易请求中此段之前的全部内容进行哈希计算,包括:交易请求魔数、交易内容、签名者列表、哈希算法代码;
*
* [第Y+1字节] - 结束: 网关节点针对交易请求的签名;
*
*
* @author huanghaiquan
*
*/
public class TxRequestMessage implements TransactionRequest {
/**
* 交易参与者的个数的最大值;
*/
public static final int MAX_TX_PARTICIPANT_COUNT = 0xFF;
private HashDigest transactionHash;
private TransactionContent transactionContent;
private Map endpointSignatureMap = new LinkedHashMap<>();
private Map nodeSignatureMap = new LinkedHashMap<>();
static {
DataContractRegistry.register(TransactionRequest.class);
}
public TxRequestMessage(HashDigest transactionHash, TransactionContent txContent) {
this.transactionHash = transactionHash;
this.transactionContent = txContent;
}
public TxRequestMessage(TransactionRequest txRequest) {
this.transactionHash = txRequest.getTransactionHash();
this.transactionContent = txRequest.getTransactionContent();
setEndpointSignatures(txRequest.getEndpointSignatures());
setNodeSignatures(txRequest.getNodeSignatures());
}
@Override
public TransactionContent getTransactionContent() {
return this.transactionContent;
}
@Override
public DigitalSignature[] getEndpointSignatures() {
return endpointSignatureMap.values().toArray(new DigitalSignature[endpointSignatureMap.size()]);
}
@Override
public DigitalSignature[] getNodeSignatures() {
return nodeSignatureMap.values().toArray(new DigitalSignature[nodeSignatureMap.size()]);
}
public void setEndpointSignatures(Object[] endpointSignatures) {
if (endpointSignatures != null) {
for (Object object : endpointSignatures) {
DigitalSignature endpointSignature = (DigitalSignature) object;
addEndpointSignatures(endpointSignature);
}
}
return;
}
public void setNodeSignatures(Object[] nodeSignatures) {
if (nodeSignatures != null) {
for (Object object : nodeSignatures) {
DigitalSignature nodeSignature = (DigitalSignature) object;
addNodeSignatures(nodeSignature);
}
}
return;
}
private void doAddEndpointSignature(DigitalSignature signature) {
Bytes address = AddressEncoding.generateAddress(signature.getPubKey());
if (endpointSignatureMap.containsKey(address)) {
throw new IllegalArgumentException(
String.format("Participant signature of Address[%s] already exist!", address));
}
endpointSignatureMap.put(address, signature);
}
/**
* 从参与者签名列表中检查是否包含指定的参与者;
*
* @param userBid
* 参与者的身份;
* @return
*/
public boolean containsEndpointSignature(BlockchainIdentity userBid) {
return endpointSignatureMap.containsKey(userBid.getAddress());
}
public boolean containsEndpointSignature(Bytes userAddress) {
return endpointSignatureMap.containsKey(userAddress);
}
public void addEndpointSignatures(DigitalSignature... signature) {
for (DigitalSignature sign : signature) {
doAddEndpointSignature(sign);
}
}
public void addEndpointSignatures(List signature) {
for (DigitalSignature sign : signature) {
doAddEndpointSignature(sign);
}
}
/**
* 从节点签名列表中检查是否包含指定的节点;
*
* @param nodeBid
* 节点的身份;
* @return
*/
public boolean containsNodeSignature(BlockchainIdentity nodeBid) {
return nodeSignatureMap.containsKey(nodeBid.getAddress());
}
public boolean containsNodeSignature(Bytes nodeAddress) {
return nodeSignatureMap.containsKey(nodeAddress);
}
private void doAddNodeSignatures(DigitalSignature signature) {
Bytes address = AddressEncoding.generateAddress(signature.getPubKey());
if (nodeSignatureMap.containsKey(address)) {
throw new IllegalArgumentException(String.format("Node signature of Address[%s] already exist!", address));
}
nodeSignatureMap.put(address, signature);
}
public void addNodeSignatures(DigitalSignature... signature) {
for (DigitalSignature sign : signature) {
doAddNodeSignatures(sign);
}
}
public void addNodeSignatures(List signature) {
for (DigitalSignature sign : signature) {
doAddNodeSignatures(sign);
}
}
@Override
public HashDigest getTransactionHash() {
return transactionHash;
}
// public HashDigest updateHash() {
// return computeHash(this.defaultHashAlgorithm);
// }
// public HashDigest updateHash(CryptoAlgorithm hashAlgorithm) {
// return computeHash(hashAlgorithm);
// }
//
// private HashDigest computeHash(CryptoAlgorithm hashAlgorithm) {
// byte[] reqBody = getRequestBody();
// this.hash = CryptoUtils.hash(hashAlgorithm).hash(reqBody);
// return this.hash;
// }
// @Override
// public void resolvFrom(InputStream in) throws IOException {
// // 解析校验交易请求魔数;
// byte[] buff = new byte[1];
// int len = in.read(buff, 0, 1);
// if (len < 1) {
// throw new IllegalArgumentException("No bytes was read for the magic number
// [TX_REQUEST]!");
// }
// if (MagicNumber.TX_REQUEST != buff[0]) {
// throw new IllegalArgumentException("Magic number [TX_REQUEST] dismatch!");
// }
//
// // 解析交易内容;
// TxContentBlob txContentBlob = new TxContentBlob();
// txContentBlob.resolvFrom(in);
//
// // 解析参与者签名列表;
// int participantCount = NumberMask.TINY.resolveMaskedNumber(in);
// List partiSignList = new ArrayList<>();
// for (int i = 0; i < participantCount; i++) {
// DigitalSignatureBlob signature = new DigitalSignatureBlob();
// signature.resolvFrom(in);
//
// partiSignList.add(signature);
// }
//
// // 解析节点签名列表;
// int nodeCount = NumberMask.TINY.resolveMaskedNumber(in);
// List nodeSignList = new ArrayList<>();
// for (int i = 0; i < nodeCount; i++) {
// DigitalSignatureBlob nodeSign = new DigitalSignatureBlob();
// nodeSign.resolvFrom(in);
// nodeSignList.add(nodeSign);
// }
//
// // 解析哈希算法标识符;
// HashAlgorithm hashAlgorithm = HashAlgorithm.valueOf((byte) in.read());
//
// // 解析原始的哈希;
// ByteArray hash = HashEncoding.read(in);
//
// this.txContent = txContentBlob;
// addParticipantSignatures(partiSignList);
// addNodeSignatures(nodeSignList);
// this.hash = hash;
//
// // 校验原始哈希;
// byte[] bodyBytes = getRequestBody();
// ByteArray rHash = HashEncoding.computeHash(bodyBytes, hashAlgorithm);
// if (!rHash.equals(hash)) {
// throw new IllegalArgumentException("The hash is not match with request
// content!");
// }
// }
//
// /**
// * 输出交易请求消息;
// *
// * 注:此方法不会自动重新计算hash;如果消息的内容发生改变后,需要调用主动调用 {@link #updateHash()} 方法重新计算 hash;
// */
// @Override
// public void writeTo(OutputStream out) throws IOException {
// if (this.hash == null) {
// updateHash();
// }
//
// buildRequestBody(out);
//
// // 写入 hash 值;
// HashEncoding.write(hash, out);
// }
// /**
// * 生成请求体,包括:交易请求魔数、交易内容、参与者签名者列表、哈希算法代号;
// *
// * @param out
// * @throws IOException
// */
// private void buildRequestBody(OutputStream out) throws IOException {
//
// buildParticipantRequest(out);
//
// // 写入节点签名列表;
// NumberMask.TINY.writeMask(nodeSignatureMap.size(), out);
// for (DigitalSignature nodeSignatureBlob : nodeSignatureMap.values()) {
// nodeSignatureBlob.writeTo(out);
// }
//
// // 写入 hash 算法代号;
// out.write(hashAlgorithm.getAlgorithm());
// }
// /**
// * 生成参与者的请求数据;
// *
// *
// * 参与者的请求数据仅包含“交易请求模数({@link MagicNumber#TX_REQUEST })”
// * “交易内容({@link #getTransactionContent()})”
// * 和“参与者签名列表({@link #getParticipantSignatures()})”三项属性;
// *
// * @param out
// */
// public void buildParticipantRequest(OutputStream out) {
// try {
// // 写入魔数;
// out.write(MagicNumber.TX_REQUEST);
//
// // 写入交易内容;
// txContent.writeTo(out);
//
// // 写入 1 个字节的参与者签名数量;
// if (participantSignatureMap.size() > MAX_TX_PARTICIPANT_COUNT) {
// throw new IllegalArgumentException("The number of participant signatures is
// out of the max count["
// + MAX_TX_PARTICIPANT_COUNT + "]!");
// }
//
// NumberMask.TINY.writeMask(participantSignatureMap.size(), out);
// // 写入参与者签名列表;
// for (DigitalSignature digitalSignatureBlob :
// participantSignatureMap.values()) {
// digitalSignatureBlob.writeTo(out);
// }
//
// } catch (IOException e) {
// throw new RuntimeIOException(e.getMessage(), e);
// }
// }
//
// @Override
// public void writeExternal(ObjectOutput out) throws IOException {
// ByteArrayOutputStream os = new ByteArrayOutputStream();
// writeTo(os);
// byte[] bts = os.toByteArray();
// out.writeInt(bts.length);
// out.write(bts);
// }
//
// @Override
// public void readExternal(ObjectInput in) throws IOException,
// ClassNotFoundException {
// int len = in.readInt();
// byte[] bts = new byte[len];
// in.readFully(bts);
// this.resolvFrom(new ByteArrayInputStream(bts));
// }
// @Override
// public byte[] toBytes() {
// ByteArrayOutputStream out = new ByteArrayOutputStream();
// try {
// writeTo(out);
// } catch (IOException e) {
// throw new RuntimeIOException(e.getMessage(), e);
// }
// return out.toByteArray();
// }
// @Override
// public ByteArray getHashData() {
// return ByteArray.wrap(getRequestBody());
// }
// private byte[] getRequestBody() {
// try {
// ByteArrayOutputStream out = new ByteArrayOutputStream();
// buildRequestBody(out);
//
// return out.toByteArray();
// } catch (IOException e) {
// throw new RuntimeIOException(e.getMessage(), e);
// }
// }
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy