Fixing a bug with memo deserialization

This commit is contained in:
Nelson R. Perez 2017-10-12 23:34:22 -05:00
parent 61dc72724e
commit b305faa662
5 changed files with 90 additions and 39 deletions

View file

@ -1,7 +1,22 @@
package cy.agorise.graphenej;
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.ByteArrayOutputStream;
@ -13,13 +28,6 @@ import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.logging.Level;
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
@ -210,6 +218,15 @@ public class Util {
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){
byte[] reverted = new byte[array.length];
for(int i = 0; i < reverted.length; i++){

View file

@ -1,20 +1,13 @@
package cy.agorise.graphenej.objects;
import com.google.common.primitives.Bytes;
import com.google.common.primitives.UnsignedLong;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
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.spongycastle.math.ec.ECPoint;
@ -23,8 +16,17 @@ import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
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 final static String TAG = "Memo";
@ -35,7 +37,7 @@ public class Memo implements ByteSerializable, JsonSerializable {
private Address from;
private Address to;
private long nonce;
private UnsignedLong nonce;
private byte[] message;
private String plaintextMessage;
@ -66,7 +68,7 @@ public class Memo implements ByteSerializable, JsonSerializable {
* @param nonce: Nonce used in the encryption.
* @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.to = to;
this.nonce = nonce;
@ -89,7 +91,7 @@ public class Memo implements ByteSerializable, JsonSerializable {
return this.to;
}
public long getNonce(){
public UnsignedLong getNonce(){
return this.nonce;
}
@ -235,7 +237,7 @@ public class Memo implements ByteSerializable, JsonSerializable {
new byte[]{(byte) this.message.length},
this.message);
} else {
byte[] nonceBytes = Util.revertLong(nonce);
byte[] nonceBytes = Util.revertUnsignedLong(nonce);
ECPoint senderPoint = ECKey.compressPoint(from.getPublicKey().getKey().getPubKeyPoint());
PublicKey senderPublicKey = new PublicKey(ECKey.fromPublicOnly(senderPoint));
@ -287,7 +289,7 @@ public class Memo implements ByteSerializable, JsonSerializable {
JsonObject jsonObject = json.getAsJsonObject();
String fromAddress = jsonObject.get(KEY_FROM).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();
Memo memo = null;
@ -295,6 +297,7 @@ public class Memo implements ByteSerializable, JsonSerializable {
Address from = new Address(fromAddress);
Address to = new Address(toAddress);
byte[] message = Util.hexToBytes(msg);
memo = new Memo(from, to, nonce, message);
}catch(MalformedAddressException e){
System.out.println("MalformedAddressException. Msg: "+e.getMessage());

View file

@ -4,24 +4,30 @@ import com.google.common.primitives.UnsignedLong;
import com.neovisionaries.ws.client.WebSocket;
import com.neovisionaries.ws.client.WebSocketException;
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.TransactionBroadcastSequence;
import cy.agorise.graphenej.interfaces.WitnessResponseListener;
import cy.agorise.graphenej.models.BaseResponse;
import cy.agorise.graphenej.models.WitnessResponse;
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 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.
@ -138,7 +144,7 @@ public class TransactionTest {
// Creating memo
long nonce = 1;
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
TransferOperation transferOperation1 = new TransferOperationBuilder()

View 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));
}
}

View file

@ -1,14 +1,18 @@
package cy.agorise.graphenej.objects;
import com.google.common.primitives.UnsignedLong;
import com.google.gson.JsonElement;
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.PublicKey;
import cy.agorise.graphenej.Util;
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.assertEquals;
@ -130,7 +134,7 @@ public class MemoTest {
@Test
public void shouldBeJsonObjectSerializable(){
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();
JsonObject reference = new JsonObject();
reference.addProperty("from", "BTS8RiFgs8HkcVPVobHLKEv6yL3iXcC9SWjbPVS15dDAXLG9GYhnY");
@ -144,7 +148,7 @@ public class MemoTest {
public void shouldBeByteSerializable(){
String byteReference = "0103d1fb8c7421db64d46fba7e36f428854ca06eff65698b293f37c7ffaa54e2c2b203aece7c31616c02fcc96b50d3397c0e8d33d6384655d477c300d9196c728a5ee20100000000000000104c81c2db6ebc61e3f9e0ead65c0559dd";
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();
assertEquals("Memo instance should generate a valid byte array", byteReference, Util.bytesToHex(memoBytes));
}