diff --git a/src/data/transaction/CreateOrderTransactionData.java b/src/data/transaction/CreateOrderTransactionData.java new file mode 100644 index 00000000..c157c8ba --- /dev/null +++ b/src/data/transaction/CreateOrderTransactionData.java @@ -0,0 +1,56 @@ +package data.transaction; + +import java.math.BigDecimal; + +import qora.transaction.Transaction.TransactionType; + +public class CreateOrderTransactionData extends TransactionData { + + // Properties + private byte[] creatorPublicKey; + private long haveAssetId; + private long wantAssetId; + private BigDecimal amount; + private BigDecimal price; + + // Constructors + + public CreateOrderTransactionData(byte[] creatorPublicKey, long haveAssetId, long wantAssetId, BigDecimal amount, BigDecimal price, BigDecimal fee, + long timestamp, byte[] reference, byte[] signature) { + super(TransactionType.CREATE_ASSET_ORDER, fee, creatorPublicKey, timestamp, reference, signature); + + this.creatorPublicKey = creatorPublicKey; + this.haveAssetId = haveAssetId; + this.wantAssetId = wantAssetId; + this.amount = amount; + this.price = price; + } + + public CreateOrderTransactionData(byte[] creatorPublicKey, long haveAssetId, long wantAssetId, BigDecimal amount, BigDecimal price, BigDecimal fee, + long timestamp, byte[] reference) { + this(creatorPublicKey, haveAssetId, wantAssetId, amount, price, fee, timestamp, reference, null); + } + + // Getters/Setters + + public byte[] getCreatorPublicKey() { + return this.creatorPublicKey; + } + + public long getHaveAssetId() { + return this.haveAssetId; + } + + public long getWantAssetId() { + return this.wantAssetId; + } + + public BigDecimal getAmount() { + return this.amount; + } + + public BigDecimal getPrice() { + return this.price; + } + +} diff --git a/src/qora/transaction/CreateOrderTransaction.java b/src/qora/transaction/CreateOrderTransaction.java index 83e6fef6..b8b82eac 100644 --- a/src/qora/transaction/CreateOrderTransaction.java +++ b/src/qora/transaction/CreateOrderTransaction.java @@ -1,163 +1,42 @@ package qora.transaction; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.math.BigDecimal; -import java.math.BigInteger; -import java.nio.ByteBuffer; -import java.sql.ResultSet; -import java.sql.SQLException; +import data.transaction.TransactionData; -import org.json.simple.JSONObject; - -import com.google.common.primitives.Ints; -import com.google.common.primitives.Longs; - -import database.DB; -import database.NoDataFoundException; -import qora.account.PublicKeyAccount; import qora.assets.Order; -import repository.hsqldb.HSQLDBSaver; -import transform.TransformationException; +import repository.DataException; +import repository.Repository; public class CreateOrderTransaction extends Transaction { // Properties - private Order order; - - // Property lengths - private static final int ASSET_LENGTH = 8; - private static final int AMOUNT_LENGTH = 12; - private static final int TYPELESS_LENGTH = BASE_TYPELESS_LENGTH + CREATOR_LENGTH + (ASSET_LENGTH + AMOUNT_LENGTH) * 2; // Constructors - public CreateOrderTransaction(PublicKeyAccount creator, long haveAssetId, long wantAssetId, BigDecimal amount, BigDecimal price, BigDecimal fee, - long timestamp, byte[] reference, byte[] signature) { - super(TransactionType.CREATE_ASSET_ORDER, fee, creator, timestamp, reference, signature); - - this.order = new Order(new BigInteger(this.signature), creator, haveAssetId, wantAssetId, amount, price, timestamp); + public CreateOrderTransaction(Repository repository, TransactionData transactionData) { + super(repository, transactionData); } - public CreateOrderTransaction(PublicKeyAccount creator, long haveAssetId, long wantAssetId, BigDecimal amount, BigDecimal price, BigDecimal fee, - long timestamp, byte[] reference) { - this(creator, haveAssetId, wantAssetId, amount, price, fee, timestamp, reference, null); - } - - // Getters/Setters + // Navigation public Order getOrder() { - return this.order; - } - - // More information - - public int getDataLength() { - return TYPE_LENGTH + TYPELESS_LENGTH; - } - - // Load/Save - - /** - * Load CreateOrderTransaction from DB using signature. - * - * @param signature - * @throws NoDataFoundException - * if no matching row found - * @throws SQLException - */ - protected CreateOrderTransaction(byte[] signature) throws SQLException { - super(TransactionType.CREATE_ASSET_ORDER, signature); - - ResultSet rs = DB.checkedExecute("SELECT have_asset_id, amount, want_asset_id, price FROM CreateOrderTransactions WHERE signature = ?", signature); - if (rs == null) - throw new NoDataFoundException(); - - long haveAssetId = rs.getLong(1); - BigDecimal amount = rs.getBigDecimal(2); - long wantAssetId = rs.getLong(3); - BigDecimal price = rs.getBigDecimal(4); - - this.order = new Order(new BigInteger(this.signature), this.creator, haveAssetId, wantAssetId, amount, price, this.timestamp); - } - - /** - * Load CreateOrderTransaction from DB using signature - * - * @param signature - * @return CreateOrderTransaction, or null if not found - * @throws SQLException - */ - public static CreateOrderTransaction fromSignature(byte[] signature) throws SQLException { - try { - return new CreateOrderTransaction(signature); - } catch (NoDataFoundException e) { - return null; - } - } - - @Override - public void save() throws SQLException { - super.save(); - - HSQLDBSaver saveHelper = new HSQLDBSaver("CreateAssetOrderTransactions"); - saveHelper.bind("signature", this.signature).bind("creator", this.creator.getPublicKey()).bind("have_asset_id", this.order.getHaveAssetId()) - .bind("amount", this.order.getAmount()).bind("want_asset_id", this.order.getWantAssetId()).bind("price", this.order.getPrice()); - saveHelper.execute(); - } - - // Converters - - protected static TransactionHandler parse(ByteBuffer byteBuffer) throws TransformationException { - if (byteBuffer.remaining() < TYPELESS_LENGTH) - throw new TransformationException("Byte data too short for CreateOrderTransaction"); - - // TODO + // TODO Something like: + // return this.repository.getAssetRepository().getOrder(this.transactionData); return null; } - @Override - public JSONObject toJSON() throws SQLException { - JSONObject json = getBaseJSON(); - - // TODO - - return json; - } - - public byte[] toBytes() { - try { - ByteArrayOutputStream bytes = new ByteArrayOutputStream(getDataLength()); - bytes.write(Ints.toByteArray(this.type.value)); - bytes.write(Longs.toByteArray(this.timestamp)); - bytes.write(this.reference); - - // TODO - - bytes.write(this.signature); - return bytes.toByteArray(); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - // Processing - public ValidationResult isValid() throws SQLException { + public ValidationResult isValid() throws DataException { // TODO return ValidationResult.OK; } - public void process() throws SQLException { - this.save(); - + public void process() throws DataException { // TODO } - public void orphan() throws SQLException { - this.delete(); - + public void orphan() throws DataException { // TODO } diff --git a/src/qora/transaction/Transaction.java b/src/qora/transaction/Transaction.java index cfd75f4b..7f9255e9 100644 --- a/src/qora/transaction/Transaction.java +++ b/src/qora/transaction/Transaction.java @@ -12,10 +12,8 @@ import data.transaction.TransactionData; import qora.account.PrivateKeyAccount; import qora.account.PublicKeyAccount; import qora.block.Block; -import qora.block.BlockChain; import repository.DataException; import repository.Repository; -import repository.RepositoryManager; import settings.Settings; import transform.TransformationException; import transform.Transformer; diff --git a/src/repository/hsqldb/transaction/HSQLDBCreateOrderTransactionRepository.java b/src/repository/hsqldb/transaction/HSQLDBCreateOrderTransactionRepository.java new file mode 100644 index 00000000..a0f8ccc4 --- /dev/null +++ b/src/repository/hsqldb/transaction/HSQLDBCreateOrderTransactionRepository.java @@ -0,0 +1,55 @@ +package repository.hsqldb.transaction; + +import java.math.BigDecimal; +import java.sql.ResultSet; +import java.sql.SQLException; + +import data.transaction.CreateOrderTransactionData; +import data.transaction.TransactionData; +import repository.DataException; +import repository.hsqldb.HSQLDBRepository; +import repository.hsqldb.HSQLDBSaver; + +public class HSQLDBCreateOrderTransactionRepository extends HSQLDBTransactionRepository { + + public HSQLDBCreateOrderTransactionRepository(HSQLDBRepository repository) { + super(repository); + } + + TransactionData fromBase(byte[] signature, byte[] reference, byte[] creatorPublicKey, long timestamp, BigDecimal fee) throws DataException { + try { + ResultSet rs = this.repository.checkedExecute("SELECT have_asset_id, amount, want_asset_id, price FROM CreateOrderTransactions WHERE signature = ?", + signature); + if (rs == null) + return null; + + long haveAssetId = rs.getLong(1); + BigDecimal amount = rs.getBigDecimal(2); + long wantAssetId = rs.getLong(3); + BigDecimal price = rs.getBigDecimal(4); + + return new CreateOrderTransactionData(creatorPublicKey, haveAssetId, wantAssetId, amount, price, fee, timestamp, reference, signature); + } catch (SQLException e) { + throw new DataException("Unable to fetch create order transaction from repository", e); + } + } + + @Override + public void save(TransactionData transactionData) throws DataException { + super.save(transactionData); + + CreateOrderTransactionData createOrderTransactionData = (CreateOrderTransactionData) transactionData; + + HSQLDBSaver saveHelper = new HSQLDBSaver("CreateAssetOrderTransactions"); + + saveHelper.bind("signature", createOrderTransactionData.getSignature()).bind("creator", createOrderTransactionData.getCreatorPublicKey()) + .bind("have_asset_id", createOrderTransactionData.getHaveAssetId()).bind("amount", createOrderTransactionData.getAmount()); + + try { + saveHelper.execute(this.repository); + } catch (SQLException e) { + throw new DataException("Unable to save create order transaction into repository", e); + } + } + +} diff --git a/src/repository/hsqldb/transaction/HSQLDBGenesisTransactionRepository.java b/src/repository/hsqldb/transaction/HSQLDBGenesisTransactionRepository.java index f640848a..63a7cb59 100644 --- a/src/repository/hsqldb/transaction/HSQLDBGenesisTransactionRepository.java +++ b/src/repository/hsqldb/transaction/HSQLDBGenesisTransactionRepository.java @@ -16,7 +16,7 @@ public class HSQLDBGenesisTransactionRepository extends HSQLDBTransactionReposit super(repository); } - TransactionData fromBase(byte[] signature, byte[] reference, byte[] creator, long timestamp, BigDecimal fee) throws DataException { + TransactionData fromBase(byte[] signature, byte[] reference, byte[] creatorPublicKey, long timestamp, BigDecimal fee) throws DataException { try { ResultSet rs = this.repository.checkedExecute("SELECT recipient, amount FROM GenesisTransactions WHERE signature = ?", signature); if (rs == null) diff --git a/src/repository/hsqldb/transaction/HSQLDBIssueAssetTransactionRepository.java b/src/repository/hsqldb/transaction/HSQLDBIssueAssetTransactionRepository.java index 4a32ca26..3ec1c5ca 100644 --- a/src/repository/hsqldb/transaction/HSQLDBIssueAssetTransactionRepository.java +++ b/src/repository/hsqldb/transaction/HSQLDBIssueAssetTransactionRepository.java @@ -16,7 +16,7 @@ public class HSQLDBIssueAssetTransactionRepository extends HSQLDBTransactionRepo super(repository); } - TransactionData fromBase(byte[] signature, byte[] reference, byte[] creator, long timestamp, BigDecimal fee) throws DataException { + TransactionData fromBase(byte[] signature, byte[] reference, byte[] creatorPublicKey, long timestamp, BigDecimal fee) throws DataException { try { ResultSet rs = this.repository.checkedExecute( "SELECT issuer, owner, asset_name, description, quantity, is_divisible, asset_id FROM IssueAssetTransactions WHERE signature = ?", diff --git a/src/repository/hsqldb/transaction/HSQLDBTransactionRepository.java b/src/repository/hsqldb/transaction/HSQLDBTransactionRepository.java index ad4894d7..dbf25cdc 100644 --- a/src/repository/hsqldb/transaction/HSQLDBTransactionRepository.java +++ b/src/repository/hsqldb/transaction/HSQLDBTransactionRepository.java @@ -18,11 +18,13 @@ public class HSQLDBTransactionRepository implements TransactionRepository { protected HSQLDBRepository repository; private HSQLDBGenesisTransactionRepository genesisTransactionRepository; private HSQLDBIssueAssetTransactionRepository issueAssetTransactionRepository; + private HSQLDBCreateOrderTransactionRepository createOrderTransactionRepository; public HSQLDBTransactionRepository(HSQLDBRepository repository) { this.repository = repository; - genesisTransactionRepository = new HSQLDBGenesisTransactionRepository(repository); - issueAssetTransactionRepository = new HSQLDBIssueAssetTransactionRepository(repository); + this.genesisTransactionRepository = new HSQLDBGenesisTransactionRepository(repository); + this.issueAssetTransactionRepository = new HSQLDBIssueAssetTransactionRepository(repository); + this.createOrderTransactionRepository = new HSQLDBCreateOrderTransactionRepository(repository); } public TransactionData fromSignature(byte[] signature) throws DataException { @@ -61,14 +63,17 @@ public class HSQLDBTransactionRepository implements TransactionRepository { } } - private TransactionData fromBase(TransactionType type, byte[] signature, byte[] reference, byte[] creator, long timestamp, BigDecimal fee) + private TransactionData fromBase(TransactionType type, byte[] signature, byte[] reference, byte[] creatorPublicKey, long timestamp, BigDecimal fee) throws DataException { switch (type) { case GENESIS: - return this.genesisTransactionRepository.fromBase(signature, reference, creator, timestamp, fee); + return this.genesisTransactionRepository.fromBase(signature, reference, creatorPublicKey, timestamp, fee); case ISSUE_ASSET: - return this.issueAssetTransactionRepository.fromBase(signature, reference, creator, timestamp, fee); + return this.issueAssetTransactionRepository.fromBase(signature, reference, creatorPublicKey, timestamp, fee); + + case CREATE_ASSET_ORDER: + return this.createOrderTransactionRepository.fromBase(signature, reference, creatorPublicKey, timestamp, fee); default: return null; diff --git a/src/transform/transaction/CreateOrderTransactionTransformer.java b/src/transform/transaction/CreateOrderTransactionTransformer.java new file mode 100644 index 00000000..29e84984 --- /dev/null +++ b/src/transform/transaction/CreateOrderTransactionTransformer.java @@ -0,0 +1,109 @@ +package transform.transaction; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.math.BigDecimal; +import java.nio.ByteBuffer; + +import org.json.simple.JSONObject; + +import com.google.common.hash.HashCode; +import com.google.common.primitives.Ints; +import com.google.common.primitives.Longs; + +import data.transaction.TransactionData; +import qora.account.PublicKeyAccount; +import data.transaction.CreateOrderTransactionData; +import transform.TransformationException; +import utils.Serialization; + +public class CreateOrderTransactionTransformer extends TransactionTransformer { + + // Property lengths + private static final int ASSET_ID_LENGTH = LONG_LENGTH; + private static final int AMOUNT_LENGTH = 12; + + private static final int TYPELESS_LENGTH = BASE_TYPELESS_LENGTH + (ASSET_ID_LENGTH + AMOUNT_LENGTH) * 2; + + static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException { + if (byteBuffer.remaining() < TYPELESS_LENGTH) + throw new TransformationException("Byte data too short for CreateOrderTransaction"); + + long timestamp = byteBuffer.getLong(); + + byte[] reference = new byte[REFERENCE_LENGTH]; + byteBuffer.get(reference); + + byte[] creatorPublicKey = Serialization.deserializePublicKey(byteBuffer); + + long haveAssetId = byteBuffer.getLong(); + long wantAssetId = byteBuffer.getLong(); + + BigDecimal amount = Serialization.deserializeBigDecimal(byteBuffer, AMOUNT_LENGTH); + BigDecimal price = Serialization.deserializeBigDecimal(byteBuffer, AMOUNT_LENGTH); + + BigDecimal fee = Serialization.deserializeBigDecimal(byteBuffer); + + byte[] signature = new byte[SIGNATURE_LENGTH]; + byteBuffer.get(signature); + + return new CreateOrderTransactionData(creatorPublicKey, haveAssetId, wantAssetId, amount, price, fee, timestamp, reference, signature); + } + + public static int getDataLength(TransactionData transactionData) throws TransformationException { + return TYPE_LENGTH + TYPELESS_LENGTH; + } + + public static byte[] toBytes(TransactionData transactionData) throws TransformationException { + try { + CreateOrderTransactionData createOrderTransactionData = (CreateOrderTransactionData) transactionData; + + ByteArrayOutputStream bytes = new ByteArrayOutputStream(); + + bytes.write(Ints.toByteArray(createOrderTransactionData.getType().value)); + bytes.write(Longs.toByteArray(createOrderTransactionData.getTimestamp())); + bytes.write(createOrderTransactionData.getReference()); + + bytes.write(createOrderTransactionData.getCreatorPublicKey()); + + bytes.write(Longs.toByteArray(createOrderTransactionData.getHaveAssetId())); + bytes.write(Longs.toByteArray(createOrderTransactionData.getWantAssetId())); + + Serialization.serializeBigDecimal(createOrderTransactionData.getAmount(), AMOUNT_LENGTH); + Serialization.serializeBigDecimal(createOrderTransactionData.getPrice(), AMOUNT_LENGTH); + + bytes.write(createOrderTransactionData.getSignature()); + + return bytes.toByteArray(); + } catch (IOException | ClassCastException e) { + throw new TransformationException(e); + } + } + + @SuppressWarnings("unchecked") + public static JSONObject toJSON(TransactionData transactionData) throws TransformationException { + JSONObject json = TransactionTransformer.getBaseJSON(transactionData); + + try { + CreateOrderTransactionData createOrderTransactionData = (CreateOrderTransactionData) transactionData; + + byte[] creatorPublicKey = createOrderTransactionData.getCreatorPublicKey(); + + json.put("creator", PublicKeyAccount.getAddress(creatorPublicKey)); + json.put("creatorPublicKey", HashCode.fromBytes(creatorPublicKey).toString()); + + JSONObject order = new JSONObject(); + order.put("have", createOrderTransactionData.getHaveAssetId()); + order.put("want", createOrderTransactionData.getWantAssetId()); + order.put("amount", createOrderTransactionData.getAmount().toPlainString()); + order.put("price", createOrderTransactionData.getPrice().toPlainString()); + + json.put("order", order); + } catch (ClassCastException e) { + throw new TransformationException(e); + } + + return json; + } + +} diff --git a/src/transform/transaction/GenesisTransactionTransformer.java b/src/transform/transaction/GenesisTransactionTransformer.java index d53b589e..27bce3cb 100644 --- a/src/transform/transaction/GenesisTransactionTransformer.java +++ b/src/transform/transaction/GenesisTransactionTransformer.java @@ -21,6 +21,7 @@ public class GenesisTransactionTransformer extends TransactionTransformer { // Property lengths private static final int RECIPIENT_LENGTH = ADDRESS_LENGTH; private static final int AMOUNT_LENGTH = LONG_LENGTH; + // Note that Genesis transactions don't require reference, fee or signature: private static final int TYPELESS_LENGTH = TIMESTAMP_LENGTH + RECIPIENT_LENGTH + AMOUNT_LENGTH; diff --git a/src/transform/transaction/IssueAssetTransactionTransformer.java b/src/transform/transaction/IssueAssetTransactionTransformer.java index bf206e9b..dba77495 100644 --- a/src/transform/transaction/IssueAssetTransactionTransformer.java +++ b/src/transform/transaction/IssueAssetTransactionTransformer.java @@ -27,6 +27,7 @@ public class IssueAssetTransactionTransformer extends TransactionTransformer { private static final int DESCRIPTION_SIZE_LENGTH = INT_LENGTH; private static final int QUANTITY_LENGTH = LONG_LENGTH; private static final int IS_DIVISIBLE_LENGTH = BOOLEAN_LENGTH; + private static final int TYPELESS_LENGTH = BASE_TYPELESS_LENGTH + ISSUER_LENGTH + OWNER_LENGTH + NAME_SIZE_LENGTH + DESCRIPTION_SIZE_LENGTH + QUANTITY_LENGTH + IS_DIVISIBLE_LENGTH; @@ -36,14 +37,14 @@ public class IssueAssetTransactionTransformer extends TransactionTransformer { static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException { if (byteBuffer.remaining() < TYPELESS_LENGTH) - throw new TransformationException("Byte data too short for GenesisTransaction"); + throw new TransformationException("Byte data too short for IssueAssetTransaction"); long timestamp = byteBuffer.getLong(); byte[] reference = new byte[REFERENCE_LENGTH]; byteBuffer.get(reference); - byte[] issuer = Serialization.deserializePublicKey(byteBuffer); + byte[] issuerPublicKey = Serialization.deserializePublicKey(byteBuffer); String owner = Serialization.deserializeRecipient(byteBuffer); String assetName = Serialization.deserializeSizedString(byteBuffer, MAX_NAME_SIZE); @@ -61,7 +62,7 @@ public class IssueAssetTransactionTransformer extends TransactionTransformer { byte[] signature = new byte[SIGNATURE_LENGTH]; byteBuffer.get(signature); - return new IssueAssetTransactionData(issuer, owner, assetName, description, quantity, isDivisible, fee, timestamp, reference, signature); + return new IssueAssetTransactionData(issuerPublicKey, owner, assetName, description, quantity, isDivisible, fee, timestamp, reference, signature); } public static int getDataLength(TransactionData transactionData) throws TransformationException { @@ -79,6 +80,7 @@ public class IssueAssetTransactionTransformer extends TransactionTransformer { bytes.write(Ints.toByteArray(issueAssetTransactionData.getType().value)); bytes.write(Longs.toByteArray(issueAssetTransactionData.getTimestamp())); bytes.write(issueAssetTransactionData.getReference()); + bytes.write(issueAssetTransactionData.getIssuerPublicKey()); bytes.write(Base58.decode(issueAssetTransactionData.getOwner())); diff --git a/src/transform/transaction/TransactionTransformer.java b/src/transform/transaction/TransactionTransformer.java index 18dbf89b..29f74dff 100644 --- a/src/transform/transaction/TransactionTransformer.java +++ b/src/transform/transaction/TransactionTransformer.java @@ -36,8 +36,11 @@ public class TransactionTransformer extends Transformer { case ISSUE_ASSET: return IssueAssetTransactionTransformer.fromByteBuffer(byteBuffer); + case CREATE_ASSET_ORDER: + return CreateOrderTransactionTransformer.fromByteBuffer(byteBuffer); + default: - return null; + throw new TransformationException("Unsupported transaction type"); } } @@ -49,6 +52,9 @@ public class TransactionTransformer extends Transformer { case ISSUE_ASSET: return IssueAssetTransactionTransformer.getDataLength(transactionData); + case CREATE_ASSET_ORDER: + return CreateOrderTransactionTransformer.getDataLength(transactionData); + default: throw new TransformationException("Unsupported transaction type"); } @@ -62,8 +68,11 @@ public class TransactionTransformer extends Transformer { case ISSUE_ASSET: return IssueAssetTransactionTransformer.toBytes(transactionData); + case CREATE_ASSET_ORDER: + return CreateOrderTransactionTransformer.toBytes(transactionData); + default: - return null; + throw new TransformationException("Unsupported transaction type"); } } @@ -72,8 +81,14 @@ public class TransactionTransformer extends Transformer { case GENESIS: return GenesisTransactionTransformer.toJSON(transaction); + case ISSUE_ASSET: + return IssueAssetTransactionTransformer.toJSON(transaction); + + case CREATE_ASSET_ORDER: + return CreateOrderTransactionTransformer.toJSON(transaction); + default: - return null; + throw new TransformationException("Unsupported transaction type"); } } diff --git a/src/utils/Serialization.java b/src/utils/Serialization.java index 980aff01..67e53d2d 100644 --- a/src/utils/Serialization.java +++ b/src/utils/Serialization.java @@ -14,6 +14,20 @@ import transform.Transformer; public class Serialization { + /** + * Convert BigDecimal, unscaled, to byte[] then prepend with zero bytes to specified length. + * + * @param amount + * @param length + * @return byte[8] + */ + public static byte[] serializeBigDecimal(BigDecimal amount, int length) { + byte[] amountBytes = amount.unscaledValue().toByteArray(); + byte[] output = new byte[length]; + System.arraycopy(amountBytes, 0, output, length - amountBytes.length, amountBytes.length); + return output; + } + /** * Convert BigDecimal, unscaled, to byte[] then prepend with zero bytes to fixed length of 8. * @@ -21,16 +35,17 @@ public class Serialization { * @return byte[8] */ public static byte[] serializeBigDecimal(BigDecimal amount) { - byte[] amountBytes = amount.unscaledValue().toByteArray(); - byte[] output = new byte[8]; - System.arraycopy(amountBytes, 0, output, 8 - amountBytes.length, amountBytes.length); - return output; + return serializeBigDecimal(amount, 8); + } + + public static BigDecimal deserializeBigDecimal(ByteBuffer byteBuffer, int length) { + byte[] bytes = new byte[length]; + byteBuffer.get(bytes); + return new BigDecimal(new BigInteger(bytes), 8); } public static BigDecimal deserializeBigDecimal(ByteBuffer byteBuffer) { - byte[] bytes = new byte[8]; - byteBuffer.get(bytes); - return new BigDecimal(new BigInteger(bytes), 8); + return Serialization.deserializeBigDecimal(byteBuffer, 8); } public static String deserializeRecipient(ByteBuffer byteBuffer) {