All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.jd.blockchain.transaction.TxRequestMessage Maven / Gradle / Ivy

There is a newer version: 1.6.5.RELEASE
Show newest version
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