|
2 | 2 |
|
3 | 3 | import java.nio.ByteBuffer; |
4 | 4 | import java.nio.ByteOrder; |
| 5 | +import java.util.HashMap; |
| 6 | +import java.util.Map; |
5 | 7 | import org.arkecosystem.crypto.encoding.Hex; |
6 | 8 | import org.arkecosystem.crypto.enums.CoreTransactionTypes; |
7 | | -import org.arkecosystem.crypto.enums.TransactionTypeGroup; |
8 | | -import org.arkecosystem.crypto.identities.Address; |
9 | | -import org.arkecosystem.crypto.transactions.deserializers.*; |
| 9 | +import org.arkecosystem.crypto.transactions.types.*; |
10 | 10 |
|
11 | 11 | public class Deserializer { |
12 | 12 |
|
13 | | - private String serialized; |
14 | 13 | private ByteBuffer buffer; |
15 | 14 | private Transaction transaction; |
16 | 15 |
|
17 | | - public Transaction deserialize(String serialized) { |
18 | | - this.serialized = serialized; |
| 16 | + private Map<Integer, Transaction> transactionsClasses = new HashMap<>(); |
| 17 | + |
| 18 | + public Deserializer(String serialized) { |
| 19 | + this.transactionsClasses.put(CoreTransactionTypes.TRANSFER.getValue(), new Transfer()); |
| 20 | + this.transactionsClasses.put( |
| 21 | + CoreTransactionTypes.SECOND_SIGNATURE_REGISTRATION.getValue(), |
| 22 | + new SecondSignatureRegistration()); |
| 23 | + this.transactionsClasses.put( |
| 24 | + CoreTransactionTypes.DELEGATE_REGISTRATION.getValue(), new DelegateRegistration()); |
| 25 | + this.transactionsClasses.put(CoreTransactionTypes.VOTE.getValue(), new Vote()); |
| 26 | + this.transactionsClasses.put( |
| 27 | + CoreTransactionTypes.MULTI_SIGNATURE_REGISTRATION.getValue(), |
| 28 | + new MultiSignatureRegistration()); |
| 29 | + this.transactionsClasses.put(CoreTransactionTypes.IPFS.getValue(), new Ipfs()); |
| 30 | + this.transactionsClasses.put( |
| 31 | + CoreTransactionTypes.MULTI_PAYMENT.getValue(), new MultiPayment()); |
| 32 | + this.transactionsClasses.put( |
| 33 | + CoreTransactionTypes.DELEGATE_RESIGNATION.getValue(), new DelegateResignation()); |
| 34 | + this.transactionsClasses.put(CoreTransactionTypes.HTLC_LOCK.getValue(), new HtlcLock()); |
| 35 | + this.transactionsClasses.put(CoreTransactionTypes.HTLC_CLAIM.getValue(), new HtlcClaim()); |
| 36 | + this.transactionsClasses.put(CoreTransactionTypes.HTLC_REFUND.getValue(), new HtlcRefund()); |
| 37 | + |
19 | 38 | this.buffer = ByteBuffer.wrap(Hex.decode(serialized)).slice(); |
20 | 39 | this.buffer.order(ByteOrder.LITTLE_ENDIAN); |
| 40 | + } |
| 41 | + |
| 42 | + public Transaction deserialize() { |
21 | 43 | this.buffer.get(); |
22 | 44 |
|
23 | | - this.transaction = new Transaction(); |
| 45 | + deserializeCommon(); |
| 46 | + deserializeVendorField(); |
24 | 47 |
|
25 | | - int assetOffset = deserializeHeader(); |
26 | | - deserializeTypeSpecific(assetOffset); |
| 48 | + this.transaction.deserialize(this.buffer); |
27 | 49 |
|
28 | | - deserializeVersionOne(); |
| 50 | + deserializeSignature(); |
| 51 | + |
| 52 | + this.transaction.computeId(); |
29 | 53 |
|
30 | 54 | return this.transaction; |
31 | 55 | } |
32 | 56 |
|
33 | | - private int deserializeHeader() { |
34 | | - transaction.version = this.buffer.get(); |
35 | | - transaction.network = this.buffer.get(); |
36 | | - if (transaction.version == 1) { |
37 | | - transaction.type = CoreTransactionTypes.values()[this.buffer.get()].getValue(); |
38 | | - transaction.timestamp = this.buffer.getInt(); |
39 | | - } else { |
40 | | - transaction.typeGroup = TransactionTypeGroup.values()[this.buffer.getInt()].getValue(); |
41 | | - transaction.type = CoreTransactionTypes.values()[this.buffer.getShort()].getValue(); |
42 | | - transaction.nonce = this.buffer.getLong(); |
43 | | - } |
| 57 | + private void deserializeCommon() { |
| 58 | + int version = this.buffer.get(); |
| 59 | + int network = this.buffer.get(); |
| 60 | + int typeGroup = this.buffer.getInt(); |
| 61 | + int type = this.buffer.getShort(); |
| 62 | + long nonce = this.buffer.getLong(); |
| 63 | + |
| 64 | + this.transaction = this.transactionsClasses.get(type); |
| 65 | + this.transaction.version = version; |
| 66 | + this.transaction.network = network; |
| 67 | + this.transaction.typeGroup = typeGroup; |
| 68 | + this.transaction.type = type; |
| 69 | + this.transaction.nonce = nonce; |
| 70 | + |
44 | 71 | byte[] senderPublicKey = new byte[33]; |
45 | 72 | this.buffer.get(senderPublicKey); |
46 | | - transaction.senderPublicKey = Hex.encode(senderPublicKey); |
| 73 | + this.transaction.senderPublicKey = Hex.encode(senderPublicKey); |
47 | 74 |
|
48 | | - transaction.fee = this.buffer.getLong(); |
| 75 | + this.transaction.fee = this.buffer.getLong(); |
| 76 | + } |
49 | 77 |
|
| 78 | + private void deserializeVendorField() { |
50 | 79 | int vendorFieldLength = this.buffer.get(); |
51 | 80 | if (vendorFieldLength > 0) { |
52 | | - byte[] vendorFieldHex = new byte[vendorFieldLength]; |
53 | | - this.buffer.get(vendorFieldHex); |
54 | | - transaction.vendorFieldHex = Hex.encode(vendorFieldHex); |
55 | | - } |
56 | | - |
57 | | - if (transaction.version == 1) { |
58 | | - return (41 + 8 + 1) * 2 + vendorFieldLength * 2; |
59 | | - } else { |
60 | | - return 59 * 2 + vendorFieldLength * 2; |
| 81 | + byte[] vendorField = new byte[vendorFieldLength]; |
| 82 | + this.buffer.get(vendorField); |
| 83 | + transaction.vendorField = new String(vendorField); |
61 | 84 | } |
62 | 85 | } |
63 | 86 |
|
64 | | - private void deserializeTypeSpecific(int assetOffset) { |
65 | | - CoreTransactionTypes transactionType = CoreTransactionTypes.values()[transaction.type]; |
66 | | - switch (transactionType) { |
67 | | - case TRANSFER: |
68 | | - new Transfer(this.serialized, this.buffer, this.transaction) |
69 | | - .deserialize(assetOffset); |
70 | | - break; |
71 | | - case SECOND_SIGNATURE_REGISTRATION: |
72 | | - new SecondSignatureRegistration(this.serialized, this.buffer, this.transaction) |
73 | | - .deserialize(assetOffset); |
74 | | - break; |
75 | | - case DELEGATE_REGISTRATION: |
76 | | - new DelegateRegistration(this.serialized, this.buffer, this.transaction) |
77 | | - .deserialize(assetOffset); |
78 | | - break; |
79 | | - case VOTE: |
80 | | - new Vote(this.serialized, this.buffer, this.transaction).deserialize(assetOffset); |
81 | | - break; |
82 | | - case MULTI_SIGNATURE_REGISTRATION: |
83 | | - new MultiSignatureRegistration(this.serialized, this.buffer, this.transaction) |
84 | | - .deserialize(assetOffset); |
85 | | - break; |
86 | | - case IPFS: |
87 | | - new Ipfs(this.serialized, this.buffer, this.transaction).deserialize(assetOffset); |
88 | | - break; |
89 | | - case MULTI_PAYMENT: |
90 | | - new MultiPayment(this.serialized, this.buffer, this.transaction) |
91 | | - .deserialize(assetOffset); |
92 | | - break; |
93 | | - case DELEGATE_RESIGNATION: |
94 | | - new DelegateResignation(this.serialized, this.buffer, this.transaction) |
95 | | - .deserialize(assetOffset); |
96 | | - break; |
97 | | - case HTLC_LOCK: |
98 | | - new HtlcLock(this.serialized, this.buffer, this.transaction) |
99 | | - .deserialize(assetOffset); |
100 | | - break; |
101 | | - case HTLC_CLAIM: |
102 | | - new HtlcClaim(this.serialized, this.buffer, this.transaction) |
103 | | - .deserialize(assetOffset); |
104 | | - break; |
105 | | - case HTLC_REFUND: |
106 | | - new HtlcRefund(this.serialized, this.buffer, this.transaction) |
107 | | - .deserialize(assetOffset); |
108 | | - break; |
109 | | - default: |
110 | | - throw new UnsupportedOperationException(); |
| 87 | + private void deserializeSignature() { |
| 88 | + if (buffer.remaining() != 0) { |
| 89 | + int signatureLength = currentSignatureLength(); |
| 90 | + byte[] signatureBuffer = new byte[signatureLength]; |
| 91 | + this.buffer.get(signatureBuffer); |
| 92 | + this.transaction.signature = Hex.encode(signatureBuffer); |
111 | 93 | } |
112 | | - } |
113 | 94 |
|
114 | | - private void deserializeVersionOne() { |
115 | | - if (transaction.secondSignature != null) { |
116 | | - transaction.signSignature = transaction.secondSignature; |
117 | | - } |
118 | | - |
119 | | - if (transaction.type == CoreTransactionTypes.VOTE.getValue()) { |
120 | | - transaction.recipientId = |
121 | | - Address.fromPublicKey(transaction.senderPublicKey, transaction.network); |
122 | | - } |
123 | | - |
124 | | - if (transaction.type == CoreTransactionTypes.MULTI_SIGNATURE_REGISTRATION.getValue()) { |
125 | | - for (int i = 0; i < transaction.asset.multisignature.keysgroup.size(); i++) { |
126 | | - transaction.asset.multisignature.keysgroup.set( |
127 | | - i, "+" + transaction.asset.multisignature.keysgroup.get(i)); |
128 | | - } |
129 | | - } |
130 | | - |
131 | | - if (transaction.vendorFieldHex != null) { |
132 | | - transaction.vendorField = new String(Hex.decode(transaction.vendorFieldHex)); |
133 | | - } |
134 | | - |
135 | | - if (transaction.id == null) { |
136 | | - transaction.id = transaction.computeId(); |
| 95 | + if (buffer.remaining() != 0) { |
| 96 | + int signatureLength = currentSignatureLength(); |
| 97 | + byte[] signatureBuffer = new byte[signatureLength]; |
| 98 | + this.buffer.get(signatureBuffer); |
| 99 | + this.transaction.secondSignature = Hex.encode(signatureBuffer); |
137 | 100 | } |
| 101 | + } |
138 | 102 |
|
139 | | - if (transaction.type == CoreTransactionTypes.SECOND_SIGNATURE_REGISTRATION.getValue() |
140 | | - || transaction.type |
141 | | - == CoreTransactionTypes.MULTI_SIGNATURE_REGISTRATION.getValue()) { |
142 | | - transaction.recipientId = |
143 | | - Address.fromPublicKey(transaction.senderPublicKey, transaction.network); |
144 | | - } |
| 103 | + private int currentSignatureLength() { |
| 104 | + int mark = this.buffer.position(); |
| 105 | + this.buffer.position(mark + 1); |
| 106 | + String length = String.valueOf(this.buffer.get()); |
| 107 | + int signatureLength = Integer.parseInt(length) + 2; |
| 108 | + this.buffer.position(mark); |
| 109 | + return signatureLength; |
145 | 110 | } |
146 | 111 | } |
0 commit comments