mirror of
https://github.com/Qortal/qortal.git
synced 2025-04-23 11:27:51 +00:00
Added CancelNameSaleTransactions + fixed dodgy UTF-8 [d]serialization/getDataLength()
This commit is contained in:
parent
0fc17d76ae
commit
c8be77e7cc
36
src/data/transaction/CancelSellNameTransactionData.java
Normal file
36
src/data/transaction/CancelSellNameTransactionData.java
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
package data.transaction;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
|
import qora.transaction.Transaction.TransactionType;
|
||||||
|
|
||||||
|
public class CancelSellNameTransactionData extends TransactionData {
|
||||||
|
|
||||||
|
// Properties
|
||||||
|
private byte[] ownerPublicKey;
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
// Constructors
|
||||||
|
|
||||||
|
public CancelSellNameTransactionData(byte[] ownerPublicKey, String name, BigDecimal fee, long timestamp, byte[] reference, byte[] signature) {
|
||||||
|
super(TransactionType.CANCEL_SELL_NAME, fee, ownerPublicKey, timestamp, reference, signature);
|
||||||
|
|
||||||
|
this.ownerPublicKey = ownerPublicKey;
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CancelSellNameTransactionData(byte[] ownerPublicKey, String name, BigDecimal fee, long timestamp, byte[] reference) {
|
||||||
|
this(ownerPublicKey, name, fee, timestamp, reference, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Getters / setters
|
||||||
|
|
||||||
|
public byte[] getOwnerPublicKey() {
|
||||||
|
return this.ownerPublicKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return this.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,6 +1,7 @@
|
|||||||
package qora.naming;
|
package qora.naming;
|
||||||
|
|
||||||
import data.naming.NameData;
|
import data.naming.NameData;
|
||||||
|
import data.transaction.CancelSellNameTransactionData;
|
||||||
import data.transaction.RegisterNameTransactionData;
|
import data.transaction.RegisterNameTransactionData;
|
||||||
import data.transaction.SellNameTransactionData;
|
import data.transaction.SellNameTransactionData;
|
||||||
import data.transaction.TransactionData;
|
import data.transaction.TransactionData;
|
||||||
@ -118,4 +119,20 @@ public class Name {
|
|||||||
this.repository.getNameRepository().save(this.nameData);
|
this.repository.getNameRepository().save(this.nameData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void sell(CancelSellNameTransactionData cancelSellNameTransactionData) throws DataException {
|
||||||
|
// Mark not for-sale but leave price in case we want to orphan
|
||||||
|
this.nameData.setIsForSale(false);
|
||||||
|
|
||||||
|
// Save sale info into repository
|
||||||
|
this.repository.getNameRepository().save(this.nameData);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void unsell(CancelSellNameTransactionData cancelSellNameTransactionData) throws DataException {
|
||||||
|
// Mark as for-sale using existing price
|
||||||
|
this.nameData.setIsForSale(true);
|
||||||
|
|
||||||
|
// Save no-sale info into repository
|
||||||
|
this.repository.getNameRepository().save(this.nameData);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
145
src/qora/transaction/CancelSellNameTransaction.java
Normal file
145
src/qora/transaction/CancelSellNameTransaction.java
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
package qora.transaction;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.google.common.base.Utf8;
|
||||||
|
|
||||||
|
import data.naming.NameData;
|
||||||
|
import data.transaction.CancelSellNameTransactionData;
|
||||||
|
import data.transaction.TransactionData;
|
||||||
|
import qora.account.Account;
|
||||||
|
import qora.account.PublicKeyAccount;
|
||||||
|
import qora.assets.Asset;
|
||||||
|
import qora.naming.Name;
|
||||||
|
import repository.DataException;
|
||||||
|
import repository.Repository;
|
||||||
|
|
||||||
|
public class CancelSellNameTransaction extends Transaction {
|
||||||
|
|
||||||
|
// Properties
|
||||||
|
private CancelSellNameTransactionData cancelSellNameTransactionData;
|
||||||
|
|
||||||
|
// Constructors
|
||||||
|
|
||||||
|
public CancelSellNameTransaction(Repository repository, TransactionData transactionData) {
|
||||||
|
super(repository, transactionData);
|
||||||
|
|
||||||
|
this.cancelSellNameTransactionData = (CancelSellNameTransactionData) this.transactionData;
|
||||||
|
}
|
||||||
|
|
||||||
|
// More information
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Account> getRecipientAccounts() {
|
||||||
|
return new ArrayList<Account>();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isInvolved(Account account) throws DataException {
|
||||||
|
String address = account.getAddress();
|
||||||
|
|
||||||
|
if (address.equals(this.getOwner().getAddress()))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BigDecimal getAmount(Account account) throws DataException {
|
||||||
|
String address = account.getAddress();
|
||||||
|
BigDecimal amount = BigDecimal.ZERO.setScale(8);
|
||||||
|
|
||||||
|
if (address.equals(this.getOwner().getAddress()))
|
||||||
|
amount = amount.subtract(this.transactionData.getFee());
|
||||||
|
|
||||||
|
return amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Navigation
|
||||||
|
|
||||||
|
public Account getOwner() throws DataException {
|
||||||
|
return new PublicKeyAccount(this.repository, this.cancelSellNameTransactionData.getOwnerPublicKey());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Processing
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ValidationResult isValid() throws DataException {
|
||||||
|
// Check name size bounds
|
||||||
|
int nameLength = Utf8.encodedLength(cancelSellNameTransactionData.getName());
|
||||||
|
if (nameLength < 1 || nameLength > Name.MAX_NAME_SIZE)
|
||||||
|
return ValidationResult.INVALID_NAME_LENGTH;
|
||||||
|
|
||||||
|
// Check name is lowercase
|
||||||
|
if (!cancelSellNameTransactionData.getName().equals(cancelSellNameTransactionData.getName().toLowerCase()))
|
||||||
|
return ValidationResult.NAME_NOT_LOWER_CASE;
|
||||||
|
|
||||||
|
NameData nameData = this.repository.getNameRepository().fromName(cancelSellNameTransactionData.getName());
|
||||||
|
|
||||||
|
// Check name exists
|
||||||
|
if (nameData == null)
|
||||||
|
return ValidationResult.NAME_DOES_NOT_EXIST;
|
||||||
|
|
||||||
|
// Check name is currently for sale
|
||||||
|
if (!nameData.getIsForSale())
|
||||||
|
return ValidationResult.NAME_NOT_FOR_SALE;
|
||||||
|
|
||||||
|
// Check transaction's public key matches name's current owner
|
||||||
|
Account owner = new PublicKeyAccount(this.repository, cancelSellNameTransactionData.getOwnerPublicKey());
|
||||||
|
if (!owner.getAddress().equals(nameData.getOwner()))
|
||||||
|
return ValidationResult.INVALID_NAME_OWNER;
|
||||||
|
|
||||||
|
// Check fee is positive
|
||||||
|
if (cancelSellNameTransactionData.getFee().compareTo(BigDecimal.ZERO) <= 0)
|
||||||
|
return ValidationResult.NEGATIVE_FEE;
|
||||||
|
|
||||||
|
// Check reference is correct
|
||||||
|
if (!Arrays.equals(owner.getLastReference(), cancelSellNameTransactionData.getReference()))
|
||||||
|
return ValidationResult.INVALID_REFERENCE;
|
||||||
|
|
||||||
|
// Check issuer has enough funds
|
||||||
|
if (owner.getConfirmedBalance(Asset.QORA).compareTo(cancelSellNameTransactionData.getFee()) == -1)
|
||||||
|
return ValidationResult.NO_BALANCE;
|
||||||
|
|
||||||
|
return ValidationResult.OK;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void process() throws DataException {
|
||||||
|
// Update Name
|
||||||
|
Name name = new Name(this.repository, cancelSellNameTransactionData.getName());
|
||||||
|
name.sell(cancelSellNameTransactionData);
|
||||||
|
|
||||||
|
// Save this transaction, now with updated "name reference" to previous transaction that updated name
|
||||||
|
this.repository.getTransactionRepository().save(cancelSellNameTransactionData);
|
||||||
|
|
||||||
|
// Update owner's balance
|
||||||
|
Account owner = new PublicKeyAccount(this.repository, cancelSellNameTransactionData.getOwnerPublicKey());
|
||||||
|
owner.setConfirmedBalance(Asset.QORA, owner.getConfirmedBalance(Asset.QORA).subtract(cancelSellNameTransactionData.getFee()));
|
||||||
|
|
||||||
|
// Update owner's reference
|
||||||
|
owner.setLastReference(cancelSellNameTransactionData.getSignature());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void orphan() throws DataException {
|
||||||
|
// Revert name
|
||||||
|
Name name = new Name(this.repository, cancelSellNameTransactionData.getName());
|
||||||
|
name.unsell(cancelSellNameTransactionData);
|
||||||
|
|
||||||
|
// Delete this transaction itself
|
||||||
|
this.repository.getTransactionRepository().delete(cancelSellNameTransactionData);
|
||||||
|
|
||||||
|
// Update owner's balance
|
||||||
|
Account owner = new PublicKeyAccount(this.repository, cancelSellNameTransactionData.getOwnerPublicKey());
|
||||||
|
owner.setConfirmedBalance(Asset.QORA, owner.getConfirmedBalance(Asset.QORA).add(cancelSellNameTransactionData.getFee()));
|
||||||
|
|
||||||
|
// Update owner's reference
|
||||||
|
owner.setLastReference(cancelSellNameTransactionData.getReference());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,12 +1,13 @@
|
|||||||
package qora.transaction;
|
package qora.transaction;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.google.common.base.Utf8;
|
||||||
|
|
||||||
import data.transaction.CreatePollTransactionData;
|
import data.transaction.CreatePollTransactionData;
|
||||||
import data.transaction.TransactionData;
|
import data.transaction.TransactionData;
|
||||||
import data.voting.PollOptionData;
|
import data.voting.PollOptionData;
|
||||||
@ -84,12 +85,13 @@ public class CreatePollTransaction extends Transaction {
|
|||||||
return ValidationResult.INVALID_ADDRESS;
|
return ValidationResult.INVALID_ADDRESS;
|
||||||
|
|
||||||
// Check name size bounds
|
// Check name size bounds
|
||||||
if (createPollTransactionData.getPollName().length() < 1 || createPollTransactionData.getPollName().length() > Poll.MAX_NAME_SIZE)
|
int pollNameLength = Utf8.encodedLength(createPollTransactionData.getPollName());
|
||||||
|
if (pollNameLength < 1 || pollNameLength > Poll.MAX_NAME_SIZE)
|
||||||
return ValidationResult.INVALID_NAME_LENGTH;
|
return ValidationResult.INVALID_NAME_LENGTH;
|
||||||
|
|
||||||
// Check description size bounds
|
// Check description size bounds
|
||||||
if (createPollTransactionData.getDescription().length() < 1
|
int pollDescriptionLength = Utf8.encodedLength(createPollTransactionData.getDescription());
|
||||||
|| createPollTransactionData.getDescription().length() > Poll.MAX_DESCRIPTION_SIZE)
|
if (pollDescriptionLength < 1 || pollDescriptionLength > Poll.MAX_DESCRIPTION_SIZE)
|
||||||
return ValidationResult.INVALID_DESCRIPTION_LENGTH;
|
return ValidationResult.INVALID_DESCRIPTION_LENGTH;
|
||||||
|
|
||||||
// Check poll name is lowercase
|
// Check poll name is lowercase
|
||||||
@ -112,7 +114,7 @@ public class CreatePollTransaction extends Transaction {
|
|||||||
List<String> optionNames = new ArrayList<String>();
|
List<String> optionNames = new ArrayList<String>();
|
||||||
for (PollOptionData pollOptionData : pollOptions) {
|
for (PollOptionData pollOptionData : pollOptions) {
|
||||||
// Check option length
|
// Check option length
|
||||||
int optionNameLength = pollOptionData.getOptionName().getBytes(StandardCharsets.UTF_8).length;
|
int optionNameLength = Utf8.encodedLength(pollOptionData.getOptionName());
|
||||||
if (optionNameLength < 1 || optionNameLength > Poll.MAX_NAME_SIZE)
|
if (optionNameLength < 1 || optionNameLength > Poll.MAX_NAME_SIZE)
|
||||||
return ValidationResult.INVALID_OPTION_LENGTH;
|
return ValidationResult.INVALID_OPTION_LENGTH;
|
||||||
|
|
||||||
|
@ -5,6 +5,8 @@ import java.util.Arrays;
|
|||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.google.common.base.Utf8;
|
||||||
|
|
||||||
import data.transaction.IssueAssetTransactionData;
|
import data.transaction.IssueAssetTransactionData;
|
||||||
import data.transaction.TransactionData;
|
import data.transaction.TransactionData;
|
||||||
import qora.account.Account;
|
import qora.account.Account;
|
||||||
@ -85,12 +87,13 @@ public class IssueAssetTransaction extends Transaction {
|
|||||||
return ValidationResult.INVALID_ADDRESS;
|
return ValidationResult.INVALID_ADDRESS;
|
||||||
|
|
||||||
// Check name size bounds
|
// Check name size bounds
|
||||||
if (issueAssetTransactionData.getAssetName().length() < 1 || issueAssetTransactionData.getAssetName().length() > IssueAssetTransaction.MAX_NAME_SIZE)
|
int assetNameLength = Utf8.encodedLength(issueAssetTransactionData.getAssetName());
|
||||||
|
if (assetNameLength < 1 || assetNameLength > IssueAssetTransaction.MAX_NAME_SIZE)
|
||||||
return ValidationResult.INVALID_NAME_LENGTH;
|
return ValidationResult.INVALID_NAME_LENGTH;
|
||||||
|
|
||||||
// Check description size bounds
|
// Check description size bounds
|
||||||
if (issueAssetTransactionData.getDescription().length() < 1
|
int assetDescriptionlength = Utf8.encodedLength(issueAssetTransactionData.getDescription());
|
||||||
|| issueAssetTransactionData.getDescription().length() > IssueAssetTransaction.MAX_DESCRIPTION_SIZE)
|
if (assetDescriptionlength < 1 || assetDescriptionlength > IssueAssetTransaction.MAX_DESCRIPTION_SIZE)
|
||||||
return ValidationResult.INVALID_DESCRIPTION_LENGTH;
|
return ValidationResult.INVALID_DESCRIPTION_LENGTH;
|
||||||
|
|
||||||
// Check quantity - either 10 billion or if that's not enough: a billion billion!
|
// Check quantity - either 10 billion or if that's not enough: a billion billion!
|
||||||
|
@ -5,6 +5,8 @@ import java.util.Arrays;
|
|||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.google.common.base.Utf8;
|
||||||
|
|
||||||
import data.transaction.RegisterNameTransactionData;
|
import data.transaction.RegisterNameTransactionData;
|
||||||
import data.transaction.TransactionData;
|
import data.transaction.TransactionData;
|
||||||
import qora.account.Account;
|
import qora.account.Account;
|
||||||
@ -78,11 +80,13 @@ public class RegisterNameTransaction extends Transaction {
|
|||||||
return ValidationResult.INVALID_ADDRESS;
|
return ValidationResult.INVALID_ADDRESS;
|
||||||
|
|
||||||
// Check name size bounds
|
// Check name size bounds
|
||||||
if (registerNameTransactionData.getName().length() < 1 || registerNameTransactionData.getName().length() > Name.MAX_NAME_SIZE)
|
int nameLength = Utf8.encodedLength(registerNameTransactionData.getName());
|
||||||
|
if (nameLength < 1 || nameLength > Name.MAX_NAME_SIZE)
|
||||||
return ValidationResult.INVALID_NAME_LENGTH;
|
return ValidationResult.INVALID_NAME_LENGTH;
|
||||||
|
|
||||||
// Check value size bounds
|
// Check data size bounds
|
||||||
if (registerNameTransactionData.getData().length() < 1 || registerNameTransactionData.getData().length() > Name.MAX_DATA_SIZE)
|
int dataLength = Utf8.encodedLength(registerNameTransactionData.getData());
|
||||||
|
if (dataLength < 1 || dataLength > Name.MAX_DATA_SIZE)
|
||||||
return ValidationResult.INVALID_DATA_LENGTH;
|
return ValidationResult.INVALID_DATA_LENGTH;
|
||||||
|
|
||||||
// Check name is lowercase
|
// Check name is lowercase
|
||||||
|
@ -5,6 +5,8 @@ import java.util.ArrayList;
|
|||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.google.common.base.Utf8;
|
||||||
|
|
||||||
import data.naming.NameData;
|
import data.naming.NameData;
|
||||||
import data.transaction.SellNameTransactionData;
|
import data.transaction.SellNameTransactionData;
|
||||||
import data.transaction.TransactionData;
|
import data.transaction.TransactionData;
|
||||||
@ -68,7 +70,8 @@ public class SellNameTransaction extends Transaction {
|
|||||||
@Override
|
@Override
|
||||||
public ValidationResult isValid() throws DataException {
|
public ValidationResult isValid() throws DataException {
|
||||||
// Check name size bounds
|
// Check name size bounds
|
||||||
if (sellNameTransactionData.getName().length() < 1 || sellNameTransactionData.getName().length() > Name.MAX_NAME_SIZE)
|
int nameLength = Utf8.encodedLength(sellNameTransactionData.getName());
|
||||||
|
if (nameLength < 1 || nameLength > Name.MAX_NAME_SIZE)
|
||||||
return ValidationResult.INVALID_NAME_LENGTH;
|
return ValidationResult.INVALID_NAME_LENGTH;
|
||||||
|
|
||||||
// Check name is lowercase
|
// Check name is lowercase
|
||||||
|
@ -44,7 +44,7 @@ public abstract class Transaction {
|
|||||||
// Validation results
|
// Validation results
|
||||||
public enum ValidationResult {
|
public enum ValidationResult {
|
||||||
OK(1), INVALID_ADDRESS(2), NEGATIVE_AMOUNT(3), NEGATIVE_FEE(4), NO_BALANCE(5), INVALID_REFERENCE(6), INVALID_NAME_LENGTH(7), INVALID_VALUE_LENGTH(
|
OK(1), INVALID_ADDRESS(2), NEGATIVE_AMOUNT(3), NEGATIVE_FEE(4), NO_BALANCE(5), INVALID_REFERENCE(6), INVALID_NAME_LENGTH(7), INVALID_VALUE_LENGTH(
|
||||||
8), NAME_ALREADY_REGISTERED(9), NAME_DOES_NOT_EXIST(10), INVALID_NAME_OWNER(11), NAME_ALREADY_FOR_SALE(12), INVALID_AMOUNT(
|
8), NAME_ALREADY_REGISTERED(9), NAME_DOES_NOT_EXIST(10), INVALID_NAME_OWNER(11), NAME_ALREADY_FOR_SALE(12), NAME_NOT_FOR_SALE(13), INVALID_AMOUNT(
|
||||||
15), NAME_NOT_LOWER_CASE(17), INVALID_DESCRIPTION_LENGTH(18), INVALID_OPTIONS_COUNT(19), INVALID_OPTION_LENGTH(20), DUPLICATE_OPTION(
|
15), NAME_NOT_LOWER_CASE(17), INVALID_DESCRIPTION_LENGTH(18), INVALID_OPTIONS_COUNT(19), INVALID_OPTION_LENGTH(20), DUPLICATE_OPTION(
|
||||||
21), POLL_ALREADY_EXISTS(22), POLL_DOES_NOT_EXIST(24), POLL_OPTION_DOES_NOT_EXIST(25), ALREADY_VOTED_FOR_THAT_OPTION(
|
21), POLL_ALREADY_EXISTS(22), POLL_DOES_NOT_EXIST(24), POLL_OPTION_DOES_NOT_EXIST(25), ALREADY_VOTED_FOR_THAT_OPTION(
|
||||||
26), INVALID_DATA_LENGTH(27), INVALID_QUANTITY(28), ASSET_DOES_NOT_EXIST(29), INVALID_RETURN(30), HAVE_EQUALS_WANT(
|
26), INVALID_DATA_LENGTH(27), INVALID_QUANTITY(28), ASSET_DOES_NOT_EXIST(29), INVALID_RETURN(30), HAVE_EQUALS_WANT(
|
||||||
@ -114,6 +114,9 @@ public abstract class Transaction {
|
|||||||
case SELL_NAME:
|
case SELL_NAME:
|
||||||
return new SellNameTransaction(repository, transactionData);
|
return new SellNameTransaction(repository, transactionData);
|
||||||
|
|
||||||
|
case CANCEL_SELL_NAME:
|
||||||
|
return new CancelSellNameTransaction(repository, transactionData);
|
||||||
|
|
||||||
case CREATE_POLL:
|
case CREATE_POLL:
|
||||||
return new CreatePollTransaction(repository, transactionData);
|
return new CreatePollTransaction(repository, transactionData);
|
||||||
|
|
||||||
|
@ -5,6 +5,8 @@ import java.util.Arrays;
|
|||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.google.common.base.Utf8;
|
||||||
|
|
||||||
import data.transaction.UpdateNameTransactionData;
|
import data.transaction.UpdateNameTransactionData;
|
||||||
import data.naming.NameData;
|
import data.naming.NameData;
|
||||||
import data.transaction.TransactionData;
|
import data.transaction.TransactionData;
|
||||||
@ -79,11 +81,13 @@ public class UpdateNameTransaction extends Transaction {
|
|||||||
return ValidationResult.INVALID_ADDRESS;
|
return ValidationResult.INVALID_ADDRESS;
|
||||||
|
|
||||||
// Check name size bounds
|
// Check name size bounds
|
||||||
if (updateNameTransactionData.getName().length() < 1 || updateNameTransactionData.getName().length() > Name.MAX_NAME_SIZE)
|
int nameLength = Utf8.encodedLength(updateNameTransactionData.getName());
|
||||||
|
if (nameLength < 1 || nameLength > Name.MAX_NAME_SIZE)
|
||||||
return ValidationResult.INVALID_NAME_LENGTH;
|
return ValidationResult.INVALID_NAME_LENGTH;
|
||||||
|
|
||||||
// Check value size bounds
|
// Check new data size bounds
|
||||||
if (updateNameTransactionData.getNewData().length() < 1 || updateNameTransactionData.getNewData().length() > Name.MAX_DATA_SIZE)
|
int newDataLength = Utf8.encodedLength(updateNameTransactionData.getNewData());
|
||||||
|
if (newDataLength < 1 || newDataLength > Name.MAX_DATA_SIZE)
|
||||||
return ValidationResult.INVALID_DATA_LENGTH;
|
return ValidationResult.INVALID_DATA_LENGTH;
|
||||||
|
|
||||||
// Check name is lowercase
|
// Check name is lowercase
|
||||||
|
@ -5,6 +5,8 @@ import java.util.ArrayList;
|
|||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.google.common.base.Utf8;
|
||||||
|
|
||||||
import data.transaction.TransactionData;
|
import data.transaction.TransactionData;
|
||||||
import data.transaction.VoteOnPollTransactionData;
|
import data.transaction.VoteOnPollTransactionData;
|
||||||
import data.voting.PollData;
|
import data.voting.PollData;
|
||||||
@ -64,7 +66,8 @@ public class VoteOnPollTransaction extends Transaction {
|
|||||||
return ValidationResult.NOT_YET_RELEASED;
|
return ValidationResult.NOT_YET_RELEASED;
|
||||||
|
|
||||||
// Check name size bounds
|
// Check name size bounds
|
||||||
if (voteOnPollTransactionData.getPollName().length() < 1 || voteOnPollTransactionData.getPollName().length() > Poll.MAX_NAME_SIZE)
|
int pollNameLength = Utf8.encodedLength(voteOnPollTransactionData.getPollName());
|
||||||
|
if (pollNameLength < 1 || pollNameLength > Poll.MAX_NAME_SIZE)
|
||||||
return ValidationResult.INVALID_NAME_LENGTH;
|
return ValidationResult.INVALID_NAME_LENGTH;
|
||||||
|
|
||||||
// Check poll name is lowercase
|
// Check poll name is lowercase
|
||||||
|
@ -0,0 +1,49 @@
|
|||||||
|
package repository.hsqldb.transaction;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
|
||||||
|
import data.transaction.CancelSellNameTransactionData;
|
||||||
|
import data.transaction.TransactionData;
|
||||||
|
import repository.DataException;
|
||||||
|
import repository.hsqldb.HSQLDBRepository;
|
||||||
|
import repository.hsqldb.HSQLDBSaver;
|
||||||
|
|
||||||
|
public class HSQLDBCancelSellNameTransactionRepository extends HSQLDBTransactionRepository {
|
||||||
|
|
||||||
|
public HSQLDBCancelSellNameTransactionRepository(HSQLDBRepository repository) {
|
||||||
|
this.repository = repository;
|
||||||
|
}
|
||||||
|
|
||||||
|
TransactionData fromBase(byte[] signature, byte[] reference, byte[] ownerPublicKey, long timestamp, BigDecimal fee) throws DataException {
|
||||||
|
try {
|
||||||
|
ResultSet rs = this.repository.checkedExecute("SELECT name FROM CancelSellNameTransactions WHERE signature = ?", signature);
|
||||||
|
if (rs == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
String name = rs.getString(1);
|
||||||
|
|
||||||
|
return new CancelSellNameTransactionData(ownerPublicKey, name, fee, timestamp, reference, signature);
|
||||||
|
} catch (SQLException e) {
|
||||||
|
throw new DataException("Unable to fetch cancel sell name transaction from repository", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void save(TransactionData transactionData) throws DataException {
|
||||||
|
CancelSellNameTransactionData cancelSellNameTransactionData = (CancelSellNameTransactionData) transactionData;
|
||||||
|
|
||||||
|
HSQLDBSaver saveHelper = new HSQLDBSaver("CancelSellNameTransactions");
|
||||||
|
|
||||||
|
saveHelper.bind("signature", cancelSellNameTransactionData.getSignature()).bind("owner", cancelSellNameTransactionData.getOwnerPublicKey()).bind("name",
|
||||||
|
cancelSellNameTransactionData.getName());
|
||||||
|
|
||||||
|
try {
|
||||||
|
saveHelper.execute(this.repository);
|
||||||
|
} catch (SQLException e) {
|
||||||
|
throw new DataException("Unable to save cancel sell name transaction into repository", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -24,6 +24,7 @@ public class HSQLDBTransactionRepository implements TransactionRepository {
|
|||||||
private HSQLDBRegisterNameTransactionRepository registerNameTransactionRepository;
|
private HSQLDBRegisterNameTransactionRepository registerNameTransactionRepository;
|
||||||
private HSQLDBUpdateNameTransactionRepository updateNameTransactionRepository;
|
private HSQLDBUpdateNameTransactionRepository updateNameTransactionRepository;
|
||||||
private HSQLDBSellNameTransactionRepository sellNameTransactionRepository;
|
private HSQLDBSellNameTransactionRepository sellNameTransactionRepository;
|
||||||
|
private HSQLDBCancelSellNameTransactionRepository cancelSellNameTransactionRepository;
|
||||||
private HSQLDBCreatePollTransactionRepository createPollTransactionRepository;
|
private HSQLDBCreatePollTransactionRepository createPollTransactionRepository;
|
||||||
private HSQLDBVoteOnPollTransactionRepository voteOnPollTransactionRepository;
|
private HSQLDBVoteOnPollTransactionRepository voteOnPollTransactionRepository;
|
||||||
private HSQLDBIssueAssetTransactionRepository issueAssetTransactionRepository;
|
private HSQLDBIssueAssetTransactionRepository issueAssetTransactionRepository;
|
||||||
@ -40,6 +41,7 @@ public class HSQLDBTransactionRepository implements TransactionRepository {
|
|||||||
this.registerNameTransactionRepository = new HSQLDBRegisterNameTransactionRepository(repository);
|
this.registerNameTransactionRepository = new HSQLDBRegisterNameTransactionRepository(repository);
|
||||||
this.updateNameTransactionRepository = new HSQLDBUpdateNameTransactionRepository(repository);
|
this.updateNameTransactionRepository = new HSQLDBUpdateNameTransactionRepository(repository);
|
||||||
this.sellNameTransactionRepository = new HSQLDBSellNameTransactionRepository(repository);
|
this.sellNameTransactionRepository = new HSQLDBSellNameTransactionRepository(repository);
|
||||||
|
this.cancelSellNameTransactionRepository = new HSQLDBCancelSellNameTransactionRepository(repository);
|
||||||
this.createPollTransactionRepository = new HSQLDBCreatePollTransactionRepository(repository);
|
this.createPollTransactionRepository = new HSQLDBCreatePollTransactionRepository(repository);
|
||||||
this.voteOnPollTransactionRepository = new HSQLDBVoteOnPollTransactionRepository(repository);
|
this.voteOnPollTransactionRepository = new HSQLDBVoteOnPollTransactionRepository(repository);
|
||||||
this.issueAssetTransactionRepository = new HSQLDBIssueAssetTransactionRepository(repository);
|
this.issueAssetTransactionRepository = new HSQLDBIssueAssetTransactionRepository(repository);
|
||||||
@ -107,6 +109,9 @@ public class HSQLDBTransactionRepository implements TransactionRepository {
|
|||||||
case SELL_NAME:
|
case SELL_NAME:
|
||||||
return this.sellNameTransactionRepository.fromBase(signature, reference, creatorPublicKey, timestamp, fee);
|
return this.sellNameTransactionRepository.fromBase(signature, reference, creatorPublicKey, timestamp, fee);
|
||||||
|
|
||||||
|
case CANCEL_SELL_NAME:
|
||||||
|
return this.cancelSellNameTransactionRepository.fromBase(signature, reference, creatorPublicKey, timestamp, fee);
|
||||||
|
|
||||||
case CREATE_POLL:
|
case CREATE_POLL:
|
||||||
return this.createPollTransactionRepository.fromBase(signature, reference, creatorPublicKey, timestamp, fee);
|
return this.createPollTransactionRepository.fromBase(signature, reference, creatorPublicKey, timestamp, fee);
|
||||||
|
|
||||||
@ -247,6 +252,10 @@ public class HSQLDBTransactionRepository implements TransactionRepository {
|
|||||||
this.sellNameTransactionRepository.save(transactionData);
|
this.sellNameTransactionRepository.save(transactionData);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case CANCEL_SELL_NAME:
|
||||||
|
this.cancelSellNameTransactionRepository.save(transactionData);
|
||||||
|
break;
|
||||||
|
|
||||||
case CREATE_POLL:
|
case CREATE_POLL:
|
||||||
this.createPollTransactionRepository.save(transactionData);
|
this.createPollTransactionRepository.save(transactionData);
|
||||||
break;
|
break;
|
||||||
|
@ -101,7 +101,12 @@ public class SerializationTests extends Common {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSellNameSerialization() throws TransformationException, DataException {
|
public void testSellNameSerialization() throws TransformationException, DataException {
|
||||||
testSpecificBlockTransactions(673, TransactionType.SELL_NAME);
|
testSpecificBlockTransactions(200, TransactionType.SELL_NAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCancelSellNameSerialization() throws TransformationException, DataException {
|
||||||
|
testSpecificBlockTransactions(741, TransactionType.CANCEL_SELL_NAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -16,6 +16,7 @@ import data.account.AccountBalanceData;
|
|||||||
import data.account.AccountData;
|
import data.account.AccountData;
|
||||||
import data.block.BlockData;
|
import data.block.BlockData;
|
||||||
import data.naming.NameData;
|
import data.naming.NameData;
|
||||||
|
import data.transaction.CancelSellNameTransactionData;
|
||||||
import data.transaction.CreatePollTransactionData;
|
import data.transaction.CreatePollTransactionData;
|
||||||
import data.transaction.PaymentTransactionData;
|
import data.transaction.PaymentTransactionData;
|
||||||
import data.transaction.RegisterNameTransactionData;
|
import data.transaction.RegisterNameTransactionData;
|
||||||
@ -31,6 +32,7 @@ import qora.account.PublicKeyAccount;
|
|||||||
import qora.assets.Asset;
|
import qora.assets.Asset;
|
||||||
import qora.block.Block;
|
import qora.block.Block;
|
||||||
import qora.block.BlockChain;
|
import qora.block.BlockChain;
|
||||||
|
import qora.transaction.CancelSellNameTransaction;
|
||||||
import qora.transaction.CreatePollTransaction;
|
import qora.transaction.CreatePollTransaction;
|
||||||
import qora.transaction.PaymentTransaction;
|
import qora.transaction.PaymentTransaction;
|
||||||
import qora.transaction.RegisterNameTransaction;
|
import qora.transaction.RegisterNameTransaction;
|
||||||
@ -223,7 +225,7 @@ public class TransactionTests {
|
|||||||
byte[] nameReference = reference;
|
byte[] nameReference = reference;
|
||||||
|
|
||||||
BigDecimal fee = BigDecimal.ONE;
|
BigDecimal fee = BigDecimal.ONE;
|
||||||
long timestamp = parentBlockData.getTimestamp() + 2_000;
|
long timestamp = parentBlockData.getTimestamp() + 1_000;
|
||||||
UpdateNameTransactionData updateNameTransactionData = new UpdateNameTransactionData(sender.getPublicKey(), newOwner.getAddress(), name, newData,
|
UpdateNameTransactionData updateNameTransactionData = new UpdateNameTransactionData(sender.getPublicKey(), newOwner.getAddress(), name, newData,
|
||||||
nameReference, fee, timestamp, reference);
|
nameReference, fee, timestamp, reference);
|
||||||
|
|
||||||
@ -269,7 +271,7 @@ public class TransactionTests {
|
|||||||
BigDecimal amount = BigDecimal.valueOf(1234L).setScale(8);
|
BigDecimal amount = BigDecimal.valueOf(1234L).setScale(8);
|
||||||
|
|
||||||
BigDecimal fee = BigDecimal.ONE;
|
BigDecimal fee = BigDecimal.ONE;
|
||||||
long timestamp = parentBlockData.getTimestamp() + 2_000;
|
long timestamp = parentBlockData.getTimestamp() + 1_000;
|
||||||
SellNameTransactionData sellNameTransactionData = new SellNameTransactionData(sender.getPublicKey(), name, amount, fee, timestamp, reference);
|
SellNameTransactionData sellNameTransactionData = new SellNameTransactionData(sender.getPublicKey(), name, amount, fee, timestamp, reference);
|
||||||
|
|
||||||
Transaction sellNameTransaction = new SellNameTransaction(repository, sellNameTransactionData);
|
Transaction sellNameTransaction = new SellNameTransaction(repository, sellNameTransactionData);
|
||||||
@ -301,6 +303,61 @@ public class TransactionTests {
|
|||||||
actualNameData = this.repository.getNameRepository().fromName(name);
|
actualNameData = this.repository.getNameRepository().fromName(name);
|
||||||
assertFalse(actualNameData.getIsForSale());
|
assertFalse(actualNameData.getIsForSale());
|
||||||
assertNull(actualNameData.getSalePrice());
|
assertNull(actualNameData.getSalePrice());
|
||||||
|
|
||||||
|
// Re-process block for use by other tests
|
||||||
|
block.process();
|
||||||
|
repository.saveChanges();
|
||||||
|
|
||||||
|
// Update variables for use by other tests
|
||||||
|
reference = sender.getLastReference();
|
||||||
|
parentBlockData = block.getBlockData();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCancelSellNameTransaction() throws DataException {
|
||||||
|
// Register and sell name using another test
|
||||||
|
testSellNameTransaction();
|
||||||
|
|
||||||
|
String name = "test name";
|
||||||
|
NameData originalNameData = this.repository.getNameRepository().fromName(name);
|
||||||
|
|
||||||
|
BigDecimal fee = BigDecimal.ONE;
|
||||||
|
long timestamp = parentBlockData.getTimestamp() + 1_000;
|
||||||
|
CancelSellNameTransactionData cancelSellNameTransactionData = new CancelSellNameTransactionData(sender.getPublicKey(), name, fee, timestamp, reference);
|
||||||
|
|
||||||
|
Transaction cancelSellNameTransaction = new CancelSellNameTransaction(repository, cancelSellNameTransactionData);
|
||||||
|
cancelSellNameTransaction.calcSignature(sender);
|
||||||
|
assertTrue(cancelSellNameTransaction.isSignatureValid());
|
||||||
|
assertEquals(ValidationResult.OK, cancelSellNameTransaction.isValid());
|
||||||
|
|
||||||
|
// Forge new block with transaction
|
||||||
|
Block block = new Block(repository, parentBlockData, generator, null, null);
|
||||||
|
block.addTransaction(cancelSellNameTransactionData);
|
||||||
|
block.sign();
|
||||||
|
|
||||||
|
assertTrue("Block signatures invalid", block.isSignatureValid());
|
||||||
|
assertEquals("Block is invalid", Block.ValidationResult.OK, block.isValid());
|
||||||
|
|
||||||
|
block.process();
|
||||||
|
repository.saveChanges();
|
||||||
|
|
||||||
|
// Check name was updated
|
||||||
|
NameData actualNameData = this.repository.getNameRepository().fromName(name);
|
||||||
|
assertFalse(actualNameData.getIsForSale());
|
||||||
|
assertEquals(originalNameData.getSalePrice(), actualNameData.getSalePrice());
|
||||||
|
|
||||||
|
// Now orphan block
|
||||||
|
block.orphan();
|
||||||
|
repository.saveChanges();
|
||||||
|
|
||||||
|
// Check name has been reverted correctly
|
||||||
|
actualNameData = this.repository.getNameRepository().fromName(name);
|
||||||
|
assertTrue(actualNameData.getIsForSale());
|
||||||
|
assertEquals(originalNameData.getSalePrice(), actualNameData.getSalePrice());
|
||||||
|
|
||||||
|
// Update variables for use by other tests
|
||||||
|
reference = sender.getLastReference();
|
||||||
|
parentBlockData = block.getBlockData();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -0,0 +1,107 @@
|
|||||||
|
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.base.Utf8;
|
||||||
|
import com.google.common.hash.HashCode;
|
||||||
|
import com.google.common.primitives.Ints;
|
||||||
|
import com.google.common.primitives.Longs;
|
||||||
|
|
||||||
|
import data.transaction.CancelSellNameTransactionData;
|
||||||
|
import data.transaction.TransactionData;
|
||||||
|
import qora.account.PublicKeyAccount;
|
||||||
|
import qora.naming.Name;
|
||||||
|
import transform.TransformationException;
|
||||||
|
import utils.Serialization;
|
||||||
|
|
||||||
|
public class CancelSellNameTransactionTransformer extends TransactionTransformer {
|
||||||
|
|
||||||
|
// Property lengths
|
||||||
|
private static final int OWNER_LENGTH = PUBLIC_KEY_LENGTH;
|
||||||
|
private static final int NAME_SIZE_LENGTH = INT_LENGTH;
|
||||||
|
|
||||||
|
private static final int TYPELESS_DATALESS_LENGTH = BASE_TYPELESS_LENGTH + OWNER_LENGTH + NAME_SIZE_LENGTH;
|
||||||
|
|
||||||
|
static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException {
|
||||||
|
if (byteBuffer.remaining() < TYPELESS_DATALESS_LENGTH)
|
||||||
|
throw new TransformationException("Byte data too short for CancelSellNameTransaction");
|
||||||
|
|
||||||
|
long timestamp = byteBuffer.getLong();
|
||||||
|
|
||||||
|
byte[] reference = new byte[REFERENCE_LENGTH];
|
||||||
|
byteBuffer.get(reference);
|
||||||
|
|
||||||
|
byte[] ownerPublicKey = Serialization.deserializePublicKey(byteBuffer);
|
||||||
|
|
||||||
|
String name = Serialization.deserializeSizedString(byteBuffer, Name.MAX_NAME_SIZE);
|
||||||
|
|
||||||
|
// Still need to make sure there are enough bytes left for remaining fields
|
||||||
|
if (byteBuffer.remaining() < FEE_LENGTH + SIGNATURE_LENGTH)
|
||||||
|
throw new TransformationException("Byte data too short for CancelSellNameTransaction");
|
||||||
|
|
||||||
|
BigDecimal fee = Serialization.deserializeBigDecimal(byteBuffer);
|
||||||
|
|
||||||
|
byte[] signature = new byte[SIGNATURE_LENGTH];
|
||||||
|
byteBuffer.get(signature);
|
||||||
|
|
||||||
|
return new CancelSellNameTransactionData(ownerPublicKey, name, fee, timestamp, reference, signature);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int getDataLength(TransactionData transactionData) throws TransformationException {
|
||||||
|
CancelSellNameTransactionData cancelSellNameTransactionData = (CancelSellNameTransactionData) transactionData;
|
||||||
|
|
||||||
|
int dataLength = TYPE_LENGTH + TYPELESS_DATALESS_LENGTH + Utf8.encodedLength(cancelSellNameTransactionData.getName());
|
||||||
|
|
||||||
|
return dataLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte[] toBytes(TransactionData transactionData) throws TransformationException {
|
||||||
|
try {
|
||||||
|
CancelSellNameTransactionData cancelSellNameTransactionData = (CancelSellNameTransactionData) transactionData;
|
||||||
|
|
||||||
|
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
|
||||||
|
|
||||||
|
bytes.write(Ints.toByteArray(cancelSellNameTransactionData.getType().value));
|
||||||
|
bytes.write(Longs.toByteArray(cancelSellNameTransactionData.getTimestamp()));
|
||||||
|
bytes.write(cancelSellNameTransactionData.getReference());
|
||||||
|
|
||||||
|
bytes.write(cancelSellNameTransactionData.getOwnerPublicKey());
|
||||||
|
Serialization.serializeSizedString(bytes, cancelSellNameTransactionData.getName());
|
||||||
|
|
||||||
|
Serialization.serializeBigDecimal(bytes, cancelSellNameTransactionData.getFee());
|
||||||
|
|
||||||
|
if (cancelSellNameTransactionData.getSignature() != null)
|
||||||
|
bytes.write(cancelSellNameTransactionData.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 {
|
||||||
|
CancelSellNameTransactionData cancelSellNameTransactionData = (CancelSellNameTransactionData) transactionData;
|
||||||
|
|
||||||
|
byte[] ownerPublicKey = cancelSellNameTransactionData.getOwnerPublicKey();
|
||||||
|
|
||||||
|
json.put("owner", PublicKeyAccount.getAddress(ownerPublicKey));
|
||||||
|
json.put("ownerPublicKey", HashCode.fromBytes(ownerPublicKey).toString());
|
||||||
|
|
||||||
|
json.put("name", cancelSellNameTransactionData.getName());
|
||||||
|
} catch (ClassCastException e) {
|
||||||
|
throw new TransformationException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return json;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -10,6 +10,7 @@ import java.util.List;
|
|||||||
import org.json.simple.JSONArray;
|
import org.json.simple.JSONArray;
|
||||||
import org.json.simple.JSONObject;
|
import org.json.simple.JSONObject;
|
||||||
|
|
||||||
|
import com.google.common.base.Utf8;
|
||||||
import com.google.common.hash.HashCode;
|
import com.google.common.hash.HashCode;
|
||||||
import com.google.common.primitives.Ints;
|
import com.google.common.primitives.Ints;
|
||||||
import com.google.common.primitives.Longs;
|
import com.google.common.primitives.Longs;
|
||||||
@ -81,12 +82,12 @@ public class CreatePollTransactionTransformer extends TransactionTransformer {
|
|||||||
public static int getDataLength(TransactionData transactionData) throws TransformationException {
|
public static int getDataLength(TransactionData transactionData) throws TransformationException {
|
||||||
CreatePollTransactionData createPollTransactionData = (CreatePollTransactionData) transactionData;
|
CreatePollTransactionData createPollTransactionData = (CreatePollTransactionData) transactionData;
|
||||||
|
|
||||||
int dataLength = TYPE_LENGTH + TYPELESS_DATALESS_LENGTH + createPollTransactionData.getPollName().length()
|
int dataLength = TYPE_LENGTH + TYPELESS_DATALESS_LENGTH + Utf8.encodedLength(createPollTransactionData.getPollName())
|
||||||
+ createPollTransactionData.getDescription().length();
|
+ Utf8.encodedLength(createPollTransactionData.getDescription());
|
||||||
|
|
||||||
// Add lengths for each poll options
|
// Add lengths for each poll options
|
||||||
for (PollOptionData pollOptionData : createPollTransactionData.getPollOptions())
|
for (PollOptionData pollOptionData : createPollTransactionData.getPollOptions())
|
||||||
dataLength += INT_LENGTH + pollOptionData.getOptionName().length();
|
dataLength += INT_LENGTH + Utf8.encodedLength(pollOptionData.getOptionName());
|
||||||
|
|
||||||
return dataLength;
|
return dataLength;
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ import java.nio.ByteBuffer;
|
|||||||
|
|
||||||
import org.json.simple.JSONObject;
|
import org.json.simple.JSONObject;
|
||||||
|
|
||||||
|
import com.google.common.base.Utf8;
|
||||||
import com.google.common.hash.HashCode;
|
import com.google.common.hash.HashCode;
|
||||||
import com.google.common.primitives.Ints;
|
import com.google.common.primitives.Ints;
|
||||||
import com.google.common.primitives.Longs;
|
import com.google.common.primitives.Longs;
|
||||||
@ -65,7 +66,8 @@ public class IssueAssetTransactionTransformer extends TransactionTransformer {
|
|||||||
public static int getDataLength(TransactionData transactionData) throws TransformationException {
|
public static int getDataLength(TransactionData transactionData) throws TransformationException {
|
||||||
IssueAssetTransactionData issueAssetTransactionData = (IssueAssetTransactionData) transactionData;
|
IssueAssetTransactionData issueAssetTransactionData = (IssueAssetTransactionData) transactionData;
|
||||||
|
|
||||||
return TYPE_LENGTH + TYPELESS_LENGTH + issueAssetTransactionData.getAssetName().length() + issueAssetTransactionData.getDescription().length();
|
return TYPE_LENGTH + TYPELESS_LENGTH + Utf8.encodedLength(issueAssetTransactionData.getAssetName())
|
||||||
|
+ Utf8.encodedLength(issueAssetTransactionData.getDescription());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static byte[] toBytes(TransactionData transactionData) throws TransformationException {
|
public static byte[] toBytes(TransactionData transactionData) throws TransformationException {
|
||||||
|
@ -7,6 +7,7 @@ import java.nio.ByteBuffer;
|
|||||||
|
|
||||||
import org.json.simple.JSONObject;
|
import org.json.simple.JSONObject;
|
||||||
|
|
||||||
|
import com.google.common.base.Utf8;
|
||||||
import com.google.common.hash.HashCode;
|
import com.google.common.hash.HashCode;
|
||||||
import com.google.common.primitives.Ints;
|
import com.google.common.primitives.Ints;
|
||||||
import com.google.common.primitives.Longs;
|
import com.google.common.primitives.Longs;
|
||||||
@ -60,8 +61,8 @@ public class RegisterNameTransactionTransformer extends TransactionTransformer {
|
|||||||
public static int getDataLength(TransactionData transactionData) throws TransformationException {
|
public static int getDataLength(TransactionData transactionData) throws TransformationException {
|
||||||
RegisterNameTransactionData registerNameTransactionData = (RegisterNameTransactionData) transactionData;
|
RegisterNameTransactionData registerNameTransactionData = (RegisterNameTransactionData) transactionData;
|
||||||
|
|
||||||
int dataLength = TYPE_LENGTH + TYPELESS_DATALESS_LENGTH + registerNameTransactionData.getName().length()
|
int dataLength = TYPE_LENGTH + TYPELESS_DATALESS_LENGTH + Utf8.encodedLength(registerNameTransactionData.getName())
|
||||||
+ registerNameTransactionData.getData().length();
|
+ Utf8.encodedLength(registerNameTransactionData.getData());
|
||||||
|
|
||||||
return dataLength;
|
return dataLength;
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ import java.nio.ByteBuffer;
|
|||||||
|
|
||||||
import org.json.simple.JSONObject;
|
import org.json.simple.JSONObject;
|
||||||
|
|
||||||
|
import com.google.common.base.Utf8;
|
||||||
import com.google.common.hash.HashCode;
|
import com.google.common.hash.HashCode;
|
||||||
import com.google.common.primitives.Ints;
|
import com.google.common.primitives.Ints;
|
||||||
import com.google.common.primitives.Longs;
|
import com.google.common.primitives.Longs;
|
||||||
@ -57,7 +58,7 @@ public class SellNameTransactionTransformer extends TransactionTransformer {
|
|||||||
public static int getDataLength(TransactionData transactionData) throws TransformationException {
|
public static int getDataLength(TransactionData transactionData) throws TransformationException {
|
||||||
SellNameTransactionData sellNameTransactionData = (SellNameTransactionData) transactionData;
|
SellNameTransactionData sellNameTransactionData = (SellNameTransactionData) transactionData;
|
||||||
|
|
||||||
int dataLength = TYPE_LENGTH + TYPELESS_DATALESS_LENGTH + sellNameTransactionData.getName().length();
|
int dataLength = TYPE_LENGTH + TYPELESS_DATALESS_LENGTH + Utf8.encodedLength(sellNameTransactionData.getName());
|
||||||
|
|
||||||
return dataLength;
|
return dataLength;
|
||||||
}
|
}
|
||||||
|
@ -46,6 +46,9 @@ public class TransactionTransformer extends Transformer {
|
|||||||
case SELL_NAME:
|
case SELL_NAME:
|
||||||
return SellNameTransactionTransformer.fromByteBuffer(byteBuffer);
|
return SellNameTransactionTransformer.fromByteBuffer(byteBuffer);
|
||||||
|
|
||||||
|
case CANCEL_SELL_NAME:
|
||||||
|
return CancelSellNameTransactionTransformer.fromByteBuffer(byteBuffer);
|
||||||
|
|
||||||
case CREATE_POLL:
|
case CREATE_POLL:
|
||||||
return CreatePollTransactionTransformer.fromByteBuffer(byteBuffer);
|
return CreatePollTransactionTransformer.fromByteBuffer(byteBuffer);
|
||||||
|
|
||||||
@ -92,6 +95,9 @@ public class TransactionTransformer extends Transformer {
|
|||||||
case SELL_NAME:
|
case SELL_NAME:
|
||||||
return SellNameTransactionTransformer.getDataLength(transactionData);
|
return SellNameTransactionTransformer.getDataLength(transactionData);
|
||||||
|
|
||||||
|
case CANCEL_SELL_NAME:
|
||||||
|
return CancelSellNameTransactionTransformer.getDataLength(transactionData);
|
||||||
|
|
||||||
case CREATE_POLL:
|
case CREATE_POLL:
|
||||||
return CreatePollTransactionTransformer.getDataLength(transactionData);
|
return CreatePollTransactionTransformer.getDataLength(transactionData);
|
||||||
|
|
||||||
@ -138,6 +144,9 @@ public class TransactionTransformer extends Transformer {
|
|||||||
case SELL_NAME:
|
case SELL_NAME:
|
||||||
return SellNameTransactionTransformer.toBytes(transactionData);
|
return SellNameTransactionTransformer.toBytes(transactionData);
|
||||||
|
|
||||||
|
case CANCEL_SELL_NAME:
|
||||||
|
return CancelSellNameTransactionTransformer.toBytes(transactionData);
|
||||||
|
|
||||||
case CREATE_POLL:
|
case CREATE_POLL:
|
||||||
return CreatePollTransactionTransformer.toBytes(transactionData);
|
return CreatePollTransactionTransformer.toBytes(transactionData);
|
||||||
|
|
||||||
@ -184,6 +193,9 @@ public class TransactionTransformer extends Transformer {
|
|||||||
case SELL_NAME:
|
case SELL_NAME:
|
||||||
return SellNameTransactionTransformer.toJSON(transactionData);
|
return SellNameTransactionTransformer.toJSON(transactionData);
|
||||||
|
|
||||||
|
case CANCEL_SELL_NAME:
|
||||||
|
return CancelSellNameTransactionTransformer.toJSON(transactionData);
|
||||||
|
|
||||||
case CREATE_POLL:
|
case CREATE_POLL:
|
||||||
return CreatePollTransactionTransformer.toJSON(transactionData);
|
return CreatePollTransactionTransformer.toJSON(transactionData);
|
||||||
|
|
||||||
|
@ -7,6 +7,7 @@ import java.nio.ByteBuffer;
|
|||||||
|
|
||||||
import org.json.simple.JSONObject;
|
import org.json.simple.JSONObject;
|
||||||
|
|
||||||
|
import com.google.common.base.Utf8;
|
||||||
import com.google.common.hash.HashCode;
|
import com.google.common.hash.HashCode;
|
||||||
import com.google.common.primitives.Ints;
|
import com.google.common.primitives.Ints;
|
||||||
import com.google.common.primitives.Longs;
|
import com.google.common.primitives.Longs;
|
||||||
@ -60,8 +61,8 @@ public class UpdateNameTransactionTransformer extends TransactionTransformer {
|
|||||||
public static int getDataLength(TransactionData transactionData) throws TransformationException {
|
public static int getDataLength(TransactionData transactionData) throws TransformationException {
|
||||||
UpdateNameTransactionData updateNameTransactionData = (UpdateNameTransactionData) transactionData;
|
UpdateNameTransactionData updateNameTransactionData = (UpdateNameTransactionData) transactionData;
|
||||||
|
|
||||||
int dataLength = TYPE_LENGTH + TYPELESS_DATALESS_LENGTH + updateNameTransactionData.getName().length()
|
int dataLength = TYPE_LENGTH + TYPELESS_DATALESS_LENGTH + Utf8.encodedLength(updateNameTransactionData.getName())
|
||||||
+ updateNameTransactionData.getNewData().length();
|
+ Utf8.encodedLength(updateNameTransactionData.getNewData());
|
||||||
|
|
||||||
return dataLength;
|
return dataLength;
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ import java.nio.ByteBuffer;
|
|||||||
|
|
||||||
import org.json.simple.JSONObject;
|
import org.json.simple.JSONObject;
|
||||||
|
|
||||||
|
import com.google.common.base.Utf8;
|
||||||
import com.google.common.hash.HashCode;
|
import com.google.common.hash.HashCode;
|
||||||
import com.google.common.primitives.Ints;
|
import com.google.common.primitives.Ints;
|
||||||
import com.google.common.primitives.Longs;
|
import com.google.common.primitives.Longs;
|
||||||
@ -63,7 +64,7 @@ public class VoteOnPollTransactionTransformer extends TransactionTransformer {
|
|||||||
public static int getDataLength(TransactionData transactionData) throws TransformationException {
|
public static int getDataLength(TransactionData transactionData) throws TransformationException {
|
||||||
VoteOnPollTransactionData voteOnPollTransactionData = (VoteOnPollTransactionData) transactionData;
|
VoteOnPollTransactionData voteOnPollTransactionData = (VoteOnPollTransactionData) transactionData;
|
||||||
|
|
||||||
int dataLength = TYPE_LENGTH + TYPELESS_DATALESS_LENGTH + voteOnPollTransactionData.getPollName().length();
|
int dataLength = TYPE_LENGTH + TYPELESS_DATALESS_LENGTH + Utf8.encodedLength(voteOnPollTransactionData.getPollName());
|
||||||
|
|
||||||
return dataLength;
|
return dataLength;
|
||||||
}
|
}
|
||||||
|
@ -63,7 +63,8 @@ public class Serialization {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void serializeSizedString(ByteArrayOutputStream bytes, String string) throws UnsupportedEncodingException, IOException {
|
public static void serializeSizedString(ByteArrayOutputStream bytes, String string) throws UnsupportedEncodingException, IOException {
|
||||||
bytes.write(Ints.toByteArray(string.length()));
|
byte[] stringBytes = string.getBytes("UTF-8");
|
||||||
|
bytes.write(Ints.toByteArray(stringBytes.length));
|
||||||
bytes.write(string.getBytes("UTF-8"));
|
bytes.write(string.getBytes("UTF-8"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user