Fixing a problem caused by the lack of extension byte in the serialization of the AccountOption class

This commit is contained in:
Nelson R. Perez 2017-04-19 22:22:57 -05:00
parent a848c66fb9
commit 88ca47c378
6 changed files with 150 additions and 5 deletions

View file

@ -1,14 +1,20 @@
package de.bitsharesmunich.graphenej; package de.bitsharesmunich.graphenej;
import com.google.common.primitives.Bytes; import com.google.common.primitives.Bytes;
import com.google.gson.*; import com.google.gson.JsonArray;
import de.bitsharesmunich.graphenej.errors.MalformedAddressException; import com.google.gson.JsonDeserializationContext;
import de.bitsharesmunich.graphenej.interfaces.GrapheneSerializable; import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import java.lang.reflect.Type; import java.lang.reflect.Type;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import de.bitsharesmunich.graphenej.errors.MalformedAddressException;
import de.bitsharesmunich.graphenej.interfaces.GrapheneSerializable;
/** /**
* Created by nelson on 12/5/16. * Created by nelson on 12/5/16.
*/ */
@ -107,6 +113,9 @@ public class AccountOptions implements GrapheneSerializable {
//TODO: Check this serialization //TODO: Check this serialization
byteArray.addAll(Bytes.asList(vote.toBytes())); byteArray.addAll(Bytes.asList(vote.toBytes()));
} }
// Account options's extensions
byteArray.addAll(Bytes.asList(extensions.toBytes()));
}else{ }else{
byteArray.add((byte) 0); byteArray.add((byte) 0);
} }

View file

@ -110,10 +110,28 @@ public class BrainKey {
return wif.toString(); return wif.toString();
} }
/**
* Returns the public address derived from this brain key
* @param prefix: The prefix to use in this address.
* @return An instance of the {@link Address} class
*/
public Address getPublicAddress(String prefix){
return new Address(ECKey.fromPublicOnly(getPublicKey()), prefix);
}
/**
* Brain key words getter
* @return: The word sequence that comprises this brain key
*/
public String getBrainKey(){ public String getBrainKey(){
return mBrainKey; return mBrainKey;
} }
/**
* Sequence number getter
* @return: The sequence number used alongside with the brain key words in order
* to derive the private key
*/
public int getSequenceNumber(){ public int getSequenceNumber(){
return sequenceNumber; return sequenceNumber;
} }

View file

@ -1,10 +1,19 @@
package de.bitsharesmunich.graphenej; package de.bitsharesmunich.graphenej;
import com.google.gson.JsonElement; import com.google.gson.JsonElement;
import de.bitsharesmunich.graphenej.interfaces.ByteSerializable;
import de.bitsharesmunich.graphenej.interfaces.GrapheneSerializable; import de.bitsharesmunich.graphenej.interfaces.GrapheneSerializable;
/** /**
* Used whenever we have an optional field. * Container template class used whenever we have an optional field.
*
* The idea here is that the binary serialization of this field should be performed
* in a specific way determined by the field implementing the {@link ByteSerializable}
* interface, more specifically using the {@link ByteSerializable#toBytes()} method.
*
* However, if the field is missing, the Optional class should be able to know how
* to serialize it, as this is always done by placing an zero byte.
*/ */
public class Optional<T extends GrapheneSerializable> implements GrapheneSerializable { public class Optional<T extends GrapheneSerializable> implements GrapheneSerializable {
private T optionalField; private T optionalField;

View file

@ -24,7 +24,6 @@ public class AccountUpdateOperation extends BaseOperation {
private Optional<Authority> owner; private Optional<Authority> owner;
private Optional<Authority> active; private Optional<Authority> active;
private Optional<AccountOptions> new_options; private Optional<AccountOptions> new_options;
private Extensions extensions;
/** /**
* Account update operation constructor. * Account update operation constructor.

View file

@ -0,0 +1,30 @@
package de.bitsharesmunich.graphenej;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
/**
* Created by nelson on 4/18/17.
*/
public class BrainKeyTest {
// public final String TEST_BRAINKEY = "SOAPILY GASSING FIFIE OZONATE WHYO TOPLINE PRISMY ZEUGMA GLOTTIC DAVEN CORODY PFUI";
public final String TEST_BRAINKEY = "BARIC BICKERN LITZ TIPFUL JINGLED POOL TUMBAK PURIST APOPYLE DURAIN SATLIJK FAUCAL";
private BrainKey mBrainKey;
@Before
public void setup(){
mBrainKey = new BrainKey(TEST_BRAINKEY, BrainKey.DEFAULT_SEQUENCE_NUMBER);
}
@Test
public void testAddress(){
Address address = mBrainKey.getPublicAddress(Address.BITSHARES_PREFIX);
// Assert.assertEquals("Assert that the address created is the expected one",
// "BTS7yT2vnjGAxPocqsnDfoJv3DHUtCNGWwqvc7mWRikkqwuhKtT5s",
// address.toString());
Assert.assertEquals("Assert that the address created is the expected one",
"BTS61UqqgE3ARuTGcckzARsdQm4EMFdBEwYyi1pbwyHrZZWrCDhT2",
address.toString());
}
}

View file

@ -0,0 +1,80 @@
package de.bitsharesmunich.graphenej.operations;
import com.google.common.primitives.UnsignedLong;
import org.bitcoinj.core.ECKey;
import org.junit.Before;
import org.junit.Test;
import java.util.ArrayList;
import java.util.HashMap;
import de.bitsharesmunich.graphenej.AccountOptions;
import de.bitsharesmunich.graphenej.Address;
import de.bitsharesmunich.graphenej.Asset;
import de.bitsharesmunich.graphenej.AssetAmount;
import de.bitsharesmunich.graphenej.Authority;
import de.bitsharesmunich.graphenej.BaseOperation;
import de.bitsharesmunich.graphenej.BlockData;
import de.bitsharesmunich.graphenej.BrainKey;
import de.bitsharesmunich.graphenej.PublicKey;
import de.bitsharesmunich.graphenej.Transaction;
import de.bitsharesmunich.graphenej.UserAccount;
import de.bitsharesmunich.graphenej.Util;
import de.bitsharesmunich.graphenej.errors.MalformedAddressException;
/**
* Created by nelson on 4/18/17.
*/
public class AccountUpdateOperationTest {
private static final String BILTHON_16_BRAIN_KEY = "SOAPILY GASSING FIFIE OZONATE WHYO TOPLINE PRISMY ZEUGMA GLOTTIC DAVEN CORODY PFUI";
public final String ADDRESS = "BTS8RYD5ehEMtTrfmeWRVKJzvLK2AqunxRh2XhXyXVxKtDjeAhYs1";
private final Asset CORE = new Asset("1.3.0");
private Authority active;
private AccountOptions options;
@Before
public void setup(){
try{
HashMap<Address, Integer> keyAuth = new HashMap<>();
keyAuth.put(new Address(ADDRESS), 1);
active = new Authority();
active.setKeyAuthorities(keyAuth);
options = new AccountOptions();
options.setMemoKey(new PublicKey(ECKey.fromPublicOnly(new Address(ADDRESS).getPublicKey().toBytes())));
options.setNumWitness(0);
options.setNum_comittee(0);
options.setVotingAccount(new UserAccount("1.2.5"));
}catch(MalformedAddressException e){
System.out.println("MalformedAddressException. Msg: "+e.getMessage());
}
}
@Test
public void testOperationSerialization(){
AccountUpdateOperationBuilder builder = new AccountUpdateOperationBuilder()
.setAccount(new UserAccount("1.2.143569"))
.setFee(new AssetAmount(UnsignedLong.valueOf(14676), CORE))
.setActive(active)
.setOptions(options);
AccountUpdateOperation operation = builder.build();
ArrayList<BaseOperation> operations = new ArrayList<>();
operations.add(operation);
ECKey privateKey = new BrainKey(BILTHON_16_BRAIN_KEY, 0).getPrivateKey();
BlockData blockData = new BlockData(3703, 2015738269, 1492551764);
Transaction tx = new Transaction(privateKey, blockData, operations);
// String json = tx.toJsonString();
byte[] serialized = tx.toBytes();
// System.out.println("json: "+json);
System.out.println("serialized: "+ Util.bytesToHex(serialized));
}
}