Fixing a bug with memo deserialization
This commit is contained in:
parent
61dc72724e
commit
b305faa662
5 changed files with 90 additions and 39 deletions
|
@ -1,7 +1,22 @@
|
||||||
package cy.agorise.graphenej;
|
package cy.agorise.graphenej;
|
||||||
|
|
||||||
import com.google.common.primitives.Bytes;
|
import com.google.common.primitives.Bytes;
|
||||||
import org.tukaani.xz.*;
|
import com.google.common.primitives.UnsignedLong;
|
||||||
|
|
||||||
|
import org.spongycastle.crypto.DataLengthException;
|
||||||
|
import org.spongycastle.crypto.InvalidCipherTextException;
|
||||||
|
import org.spongycastle.crypto.engines.AESFastEngine;
|
||||||
|
import org.spongycastle.crypto.modes.CBCBlockCipher;
|
||||||
|
import org.spongycastle.crypto.paddings.PaddedBufferedBlockCipher;
|
||||||
|
import org.spongycastle.crypto.params.KeyParameter;
|
||||||
|
import org.spongycastle.crypto.params.ParametersWithIV;
|
||||||
|
import org.tukaani.xz.CorruptedInputException;
|
||||||
|
import org.tukaani.xz.FinishableOutputStream;
|
||||||
|
import org.tukaani.xz.LZMA2Options;
|
||||||
|
import org.tukaani.xz.LZMAInputStream;
|
||||||
|
import org.tukaani.xz.LZMAOutputStream;
|
||||||
|
import org.tukaani.xz.XZInputStream;
|
||||||
|
import org.tukaani.xz.XZOutputStream;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
|
@ -13,13 +28,6 @@ import java.security.NoSuchAlgorithmException;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
import org.spongycastle.crypto.DataLengthException;
|
|
||||||
import org.spongycastle.crypto.InvalidCipherTextException;
|
|
||||||
import org.spongycastle.crypto.engines.AESFastEngine;
|
|
||||||
import org.spongycastle.crypto.modes.CBCBlockCipher;
|
|
||||||
import org.spongycastle.crypto.paddings.PaddedBufferedBlockCipher;
|
|
||||||
import org.spongycastle.crypto.params.KeyParameter;
|
|
||||||
import org.spongycastle.crypto.params.ParametersWithIV;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class used to encapsulate common utility methods
|
* Class used to encapsulate common utility methods
|
||||||
|
@ -210,6 +218,15 @@ public class Util {
|
||||||
return ByteBuffer.allocate(Long.SIZE / 8).putLong(Long.reverseBytes(input)).array();
|
return ByteBuffer.allocate(Long.SIZE / 8).putLong(Long.reverseBytes(input)).array();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Same operation as in the revertInteger function, but with an UnsignedLong object as argument.
|
||||||
|
* @param input An UnsignedLong class instance
|
||||||
|
* @return The array of bytes that represent this value in the reverse format.
|
||||||
|
*/
|
||||||
|
public static byte[] revertUnsignedLong(UnsignedLong input){
|
||||||
|
return ByteBuffer.allocate(Long.SIZE / 8).putLong(Long.reverseBytes(input.longValue())).array();
|
||||||
|
}
|
||||||
|
|
||||||
public static byte[] revertBytes(byte[] array){
|
public static byte[] revertBytes(byte[] array){
|
||||||
byte[] reverted = new byte[array.length];
|
byte[] reverted = new byte[array.length];
|
||||||
for(int i = 0; i < reverted.length; i++){
|
for(int i = 0; i < reverted.length; i++){
|
||||||
|
|
|
@ -1,20 +1,13 @@
|
||||||
package cy.agorise.graphenej.objects;
|
package cy.agorise.graphenej.objects;
|
||||||
|
|
||||||
import com.google.common.primitives.Bytes;
|
import com.google.common.primitives.Bytes;
|
||||||
|
import com.google.common.primitives.UnsignedLong;
|
||||||
import com.google.gson.JsonDeserializationContext;
|
import com.google.gson.JsonDeserializationContext;
|
||||||
import com.google.gson.JsonDeserializer;
|
import com.google.gson.JsonDeserializer;
|
||||||
import com.google.gson.JsonElement;
|
import com.google.gson.JsonElement;
|
||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
import com.google.gson.JsonParseException;
|
import com.google.gson.JsonParseException;
|
||||||
|
|
||||||
import cy.agorise.graphenej.Address;
|
|
||||||
import cy.agorise.graphenej.PublicKey;
|
|
||||||
import cy.agorise.graphenej.Util;
|
|
||||||
import cy.agorise.graphenej.errors.ChecksumException;
|
|
||||||
import cy.agorise.graphenej.errors.MalformedAddressException;
|
|
||||||
import cy.agorise.graphenej.interfaces.ByteSerializable;
|
|
||||||
import cy.agorise.graphenej.interfaces.JsonSerializable;
|
|
||||||
|
|
||||||
import org.bitcoinj.core.ECKey;
|
import org.bitcoinj.core.ECKey;
|
||||||
import org.spongycastle.math.ec.ECPoint;
|
import org.spongycastle.math.ec.ECPoint;
|
||||||
|
|
||||||
|
@ -23,8 +16,17 @@ import java.security.MessageDigest;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
import cy.agorise.graphenej.Address;
|
||||||
|
import cy.agorise.graphenej.PublicKey;
|
||||||
|
import cy.agorise.graphenej.Util;
|
||||||
|
import cy.agorise.graphenej.errors.ChecksumException;
|
||||||
|
import cy.agorise.graphenej.errors.MalformedAddressException;
|
||||||
|
import cy.agorise.graphenej.interfaces.ByteSerializable;
|
||||||
|
import cy.agorise.graphenej.interfaces.JsonSerializable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by nelson on 11/9/16.
|
* Class used to represent a memo data structure
|
||||||
|
* {@url https://bitshares.org/doxygen/structgraphene_1_1chain_1_1memo__data.html}
|
||||||
*/
|
*/
|
||||||
public class Memo implements ByteSerializable, JsonSerializable {
|
public class Memo implements ByteSerializable, JsonSerializable {
|
||||||
public final static String TAG = "Memo";
|
public final static String TAG = "Memo";
|
||||||
|
@ -35,7 +37,7 @@ public class Memo implements ByteSerializable, JsonSerializable {
|
||||||
|
|
||||||
private Address from;
|
private Address from;
|
||||||
private Address to;
|
private Address to;
|
||||||
private long nonce;
|
private UnsignedLong nonce;
|
||||||
private byte[] message;
|
private byte[] message;
|
||||||
private String plaintextMessage;
|
private String plaintextMessage;
|
||||||
|
|
||||||
|
@ -66,7 +68,7 @@ public class Memo implements ByteSerializable, JsonSerializable {
|
||||||
* @param nonce: Nonce used in the encryption.
|
* @param nonce: Nonce used in the encryption.
|
||||||
* @param message: Message in ciphertext.
|
* @param message: Message in ciphertext.
|
||||||
*/
|
*/
|
||||||
public Memo(Address from, Address to, long nonce, byte[] message){
|
public Memo(Address from, Address to, UnsignedLong nonce, byte[] message){
|
||||||
this.from = from;
|
this.from = from;
|
||||||
this.to = to;
|
this.to = to;
|
||||||
this.nonce = nonce;
|
this.nonce = nonce;
|
||||||
|
@ -89,7 +91,7 @@ public class Memo implements ByteSerializable, JsonSerializable {
|
||||||
return this.to;
|
return this.to;
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getNonce(){
|
public UnsignedLong getNonce(){
|
||||||
return this.nonce;
|
return this.nonce;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -235,7 +237,7 @@ public class Memo implements ByteSerializable, JsonSerializable {
|
||||||
new byte[]{(byte) this.message.length},
|
new byte[]{(byte) this.message.length},
|
||||||
this.message);
|
this.message);
|
||||||
} else {
|
} else {
|
||||||
byte[] nonceBytes = Util.revertLong(nonce);
|
byte[] nonceBytes = Util.revertUnsignedLong(nonce);
|
||||||
|
|
||||||
ECPoint senderPoint = ECKey.compressPoint(from.getPublicKey().getKey().getPubKeyPoint());
|
ECPoint senderPoint = ECKey.compressPoint(from.getPublicKey().getKey().getPubKeyPoint());
|
||||||
PublicKey senderPublicKey = new PublicKey(ECKey.fromPublicOnly(senderPoint));
|
PublicKey senderPublicKey = new PublicKey(ECKey.fromPublicOnly(senderPoint));
|
||||||
|
@ -287,7 +289,7 @@ public class Memo implements ByteSerializable, JsonSerializable {
|
||||||
JsonObject jsonObject = json.getAsJsonObject();
|
JsonObject jsonObject = json.getAsJsonObject();
|
||||||
String fromAddress = jsonObject.get(KEY_FROM).getAsString();
|
String fromAddress = jsonObject.get(KEY_FROM).getAsString();
|
||||||
String toAddress = jsonObject.get(KEY_TO).getAsString();
|
String toAddress = jsonObject.get(KEY_TO).getAsString();
|
||||||
long nonce = jsonObject.get(KEY_NONCE).getAsLong();
|
UnsignedLong nonce = UnsignedLong.valueOf(jsonObject.get(KEY_NONCE).getAsString());
|
||||||
String msg = jsonObject.get(KEY_MESSAGE).getAsString();
|
String msg = jsonObject.get(KEY_MESSAGE).getAsString();
|
||||||
|
|
||||||
Memo memo = null;
|
Memo memo = null;
|
||||||
|
@ -295,6 +297,7 @@ public class Memo implements ByteSerializable, JsonSerializable {
|
||||||
Address from = new Address(fromAddress);
|
Address from = new Address(fromAddress);
|
||||||
Address to = new Address(toAddress);
|
Address to = new Address(toAddress);
|
||||||
byte[] message = Util.hexToBytes(msg);
|
byte[] message = Util.hexToBytes(msg);
|
||||||
|
|
||||||
memo = new Memo(from, to, nonce, message);
|
memo = new Memo(from, to, nonce, message);
|
||||||
}catch(MalformedAddressException e){
|
}catch(MalformedAddressException e){
|
||||||
System.out.println("MalformedAddressException. Msg: "+e.getMessage());
|
System.out.println("MalformedAddressException. Msg: "+e.getMessage());
|
||||||
|
|
|
@ -4,24 +4,30 @@ import com.google.common.primitives.UnsignedLong;
|
||||||
import com.neovisionaries.ws.client.WebSocket;
|
import com.neovisionaries.ws.client.WebSocket;
|
||||||
import com.neovisionaries.ws.client.WebSocketException;
|
import com.neovisionaries.ws.client.WebSocketException;
|
||||||
import com.neovisionaries.ws.client.WebSocketFactory;
|
import com.neovisionaries.ws.client.WebSocketFactory;
|
||||||
|
|
||||||
|
import org.bitcoinj.core.ECKey;
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.net.ssl.SSLContext;
|
||||||
|
|
||||||
import cy.agorise.graphenej.api.GetLimitOrders;
|
import cy.agorise.graphenej.api.GetLimitOrders;
|
||||||
import cy.agorise.graphenej.api.TransactionBroadcastSequence;
|
import cy.agorise.graphenej.api.TransactionBroadcastSequence;
|
||||||
import cy.agorise.graphenej.interfaces.WitnessResponseListener;
|
import cy.agorise.graphenej.interfaces.WitnessResponseListener;
|
||||||
import cy.agorise.graphenej.models.BaseResponse;
|
import cy.agorise.graphenej.models.BaseResponse;
|
||||||
import cy.agorise.graphenej.models.WitnessResponse;
|
import cy.agorise.graphenej.models.WitnessResponse;
|
||||||
import cy.agorise.graphenej.objects.Memo;
|
import cy.agorise.graphenej.objects.Memo;
|
||||||
import cy.agorise.graphenej.operations.*;
|
import cy.agorise.graphenej.operations.LimitOrderCancelOperation;
|
||||||
|
import cy.agorise.graphenej.operations.LimitOrderCreateOperation;
|
||||||
|
import cy.agorise.graphenej.operations.TransferOperation;
|
||||||
|
import cy.agorise.graphenej.operations.TransferOperationBuilder;
|
||||||
import cy.agorise.graphenej.test.NaiveSSLContext;
|
import cy.agorise.graphenej.test.NaiveSSLContext;
|
||||||
import org.bitcoinj.core.ECKey;
|
|
||||||
import org.junit.Assert;
|
|
||||||
import org.junit.Before;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import javax.net.ssl.SSLContext;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.security.NoSuchAlgorithmException;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by nelson on 3/6/17.
|
* Created by nelson on 3/6/17.
|
||||||
|
@ -138,7 +144,7 @@ public class TransactionTest {
|
||||||
// Creating memo
|
// Creating memo
|
||||||
long nonce = 1;
|
long nonce = 1;
|
||||||
byte[] encryptedMessage = Memo.encryptMessage(sourcePrivateKey, to1, nonce, "another message");
|
byte[] encryptedMessage = Memo.encryptMessage(sourcePrivateKey, to1, nonce, "another message");
|
||||||
Memo memo = new Memo(new Address(ECKey.fromPublicOnly(sourcePrivateKey.getPubKey())), new Address(to1.getKey()), nonce, encryptedMessage);
|
Memo memo = new Memo(new Address(ECKey.fromPublicOnly(sourcePrivateKey.getPubKey())), new Address(to1.getKey()), UnsignedLong.valueOf(nonce), encryptedMessage);
|
||||||
|
|
||||||
// Creating operation 1
|
// Creating operation 1
|
||||||
TransferOperation transferOperation1 = new TransferOperationBuilder()
|
TransferOperation transferOperation1 = new TransferOperationBuilder()
|
||||||
|
|
21
graphenej/src/test/java/cy/agorise/graphenej/UtilTest.java
Normal file
21
graphenej/src/test/java/cy/agorise/graphenej/UtilTest.java
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
package cy.agorise.graphenej;
|
||||||
|
|
||||||
|
import com.google.common.primitives.UnsignedLong;
|
||||||
|
|
||||||
|
import junit.framework.Assert;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class used to test Util methods
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class UtilTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRevertUnsignedLong(){
|
||||||
|
UnsignedLong unsignedLong = UnsignedLong.valueOf("12179241258665439971");
|
||||||
|
byte[] reversed = Util.revertUnsignedLong(unsignedLong);
|
||||||
|
Assert.assertEquals("e3f28878655b05a9", Util.bytesToHex(reversed));
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,14 +1,18 @@
|
||||||
package cy.agorise.graphenej.objects;
|
package cy.agorise.graphenej.objects;
|
||||||
|
|
||||||
|
import com.google.common.primitives.UnsignedLong;
|
||||||
import com.google.gson.JsonElement;
|
import com.google.gson.JsonElement;
|
||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
|
|
||||||
|
import org.bitcoinj.core.DumpedPrivateKey;
|
||||||
|
import org.bitcoinj.core.ECKey;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
import cy.agorise.graphenej.Address;
|
import cy.agorise.graphenej.Address;
|
||||||
import cy.agorise.graphenej.PublicKey;
|
import cy.agorise.graphenej.PublicKey;
|
||||||
import cy.agorise.graphenej.Util;
|
import cy.agorise.graphenej.Util;
|
||||||
import cy.agorise.graphenej.errors.ChecksumException;
|
import cy.agorise.graphenej.errors.ChecksumException;
|
||||||
import org.bitcoinj.core.DumpedPrivateKey;
|
|
||||||
import org.bitcoinj.core.ECKey;
|
|
||||||
import org.junit.*;
|
|
||||||
|
|
||||||
import static org.junit.Assert.assertArrayEquals;
|
import static org.junit.Assert.assertArrayEquals;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
@ -130,7 +134,7 @@ public class MemoTest {
|
||||||
@Test
|
@Test
|
||||||
public void shouldBeJsonObjectSerializable(){
|
public void shouldBeJsonObjectSerializable(){
|
||||||
byte[] encrypted = Memo.encryptMessage(sourcePrivate, destinationAddress, 1, shortMessage);
|
byte[] encrypted = Memo.encryptMessage(sourcePrivate, destinationAddress, 1, shortMessage);
|
||||||
Memo memo = new Memo(sourceAddress, destinationAddress, 1, encrypted);
|
Memo memo = new Memo(sourceAddress, destinationAddress, UnsignedLong.ONE, encrypted);
|
||||||
JsonElement jsonObject = memo.toJsonObject();
|
JsonElement jsonObject = memo.toJsonObject();
|
||||||
JsonObject reference = new JsonObject();
|
JsonObject reference = new JsonObject();
|
||||||
reference.addProperty("from", "BTS8RiFgs8HkcVPVobHLKEv6yL3iXcC9SWjbPVS15dDAXLG9GYhnY");
|
reference.addProperty("from", "BTS8RiFgs8HkcVPVobHLKEv6yL3iXcC9SWjbPVS15dDAXLG9GYhnY");
|
||||||
|
@ -144,7 +148,7 @@ public class MemoTest {
|
||||||
public void shouldBeByteSerializable(){
|
public void shouldBeByteSerializable(){
|
||||||
String byteReference = "0103d1fb8c7421db64d46fba7e36f428854ca06eff65698b293f37c7ffaa54e2c2b203aece7c31616c02fcc96b50d3397c0e8d33d6384655d477c300d9196c728a5ee20100000000000000104c81c2db6ebc61e3f9e0ead65c0559dd";
|
String byteReference = "0103d1fb8c7421db64d46fba7e36f428854ca06eff65698b293f37c7ffaa54e2c2b203aece7c31616c02fcc96b50d3397c0e8d33d6384655d477c300d9196c728a5ee20100000000000000104c81c2db6ebc61e3f9e0ead65c0559dd";
|
||||||
byte[] encrypted = Memo.encryptMessage(sourcePrivate, destinationAddress, 1, shortMessage);
|
byte[] encrypted = Memo.encryptMessage(sourcePrivate, destinationAddress, 1, shortMessage);
|
||||||
Memo memo = new Memo(sourceAddress, destinationAddress, 1, encrypted);
|
Memo memo = new Memo(sourceAddress, destinationAddress, UnsignedLong.ONE, encrypted);
|
||||||
byte[] memoBytes = memo.toBytes();
|
byte[] memoBytes = memo.toBytes();
|
||||||
assertEquals("Memo instance should generate a valid byte array", byteReference, Util.bytesToHex(memoBytes));
|
assertEquals("Memo instance should generate a valid byte array", byteReference, Util.bytesToHex(memoBytes));
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue