mirror of
https://github.com/Qortal/qortal.git
synced 2025-08-01 14:41:23 +00:00
primary names implementation
This commit is contained in:
@@ -2,12 +2,14 @@ package org.qortal.account;
|
|||||||
|
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
|
import org.qortal.api.resource.TransactionsResource;
|
||||||
import org.qortal.block.BlockChain;
|
import org.qortal.block.BlockChain;
|
||||||
import org.qortal.controller.LiteNode;
|
import org.qortal.controller.LiteNode;
|
||||||
import org.qortal.data.account.AccountBalanceData;
|
import org.qortal.data.account.AccountBalanceData;
|
||||||
import org.qortal.data.account.AccountData;
|
import org.qortal.data.account.AccountData;
|
||||||
import org.qortal.data.account.RewardShareData;
|
import org.qortal.data.account.RewardShareData;
|
||||||
import org.qortal.data.naming.NameData;
|
import org.qortal.data.naming.NameData;
|
||||||
|
import org.qortal.data.transaction.TransactionData;
|
||||||
import org.qortal.repository.DataException;
|
import org.qortal.repository.DataException;
|
||||||
import org.qortal.repository.GroupRepository;
|
import org.qortal.repository.GroupRepository;
|
||||||
import org.qortal.repository.NameRepository;
|
import org.qortal.repository.NameRepository;
|
||||||
@@ -19,7 +21,11 @@ import org.qortal.utils.Groups;
|
|||||||
import javax.xml.bind.annotation.XmlAccessType;
|
import javax.xml.bind.annotation.XmlAccessType;
|
||||||
import javax.xml.bind.annotation.XmlAccessorType;
|
import javax.xml.bind.annotation.XmlAccessorType;
|
||||||
|
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
import static org.qortal.utils.Amounts.prettyAmount;
|
import static org.qortal.utils.Amounts.prettyAmount;
|
||||||
|
|
||||||
@@ -361,6 +367,142 @@ public class Account {
|
|||||||
return accountData.getLevel();
|
return accountData.getLevel();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Primary Name
|
||||||
|
*
|
||||||
|
* @return the primary name for this address if present, otherwise empty
|
||||||
|
*
|
||||||
|
* @throws DataException
|
||||||
|
*/
|
||||||
|
public Optional<String> getPrimaryName() throws DataException {
|
||||||
|
|
||||||
|
return this.repository.getNameRepository().getPrimaryName(this.address);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove Primary Name
|
||||||
|
*
|
||||||
|
* @throws DataException
|
||||||
|
*/
|
||||||
|
public void removePrimaryName() throws DataException {
|
||||||
|
this.repository.getNameRepository().removePrimaryName(this.address);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset Primary Name
|
||||||
|
*
|
||||||
|
* Set primary name based on the names (and their history) this account owns.
|
||||||
|
*
|
||||||
|
* @param confirmationStatus the status of the transactions for the determining the primary name
|
||||||
|
*
|
||||||
|
* @return the primary name, empty if their isn't one
|
||||||
|
*
|
||||||
|
* @throws DataException
|
||||||
|
*/
|
||||||
|
public Optional<String> resetPrimaryName(TransactionsResource.ConfirmationStatus confirmationStatus) throws DataException {
|
||||||
|
Optional<String> primaryName = determinePrimaryName(confirmationStatus);
|
||||||
|
|
||||||
|
if(primaryName.isPresent()) {
|
||||||
|
return setPrimaryName(primaryName.get());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return primaryName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine Primary Name
|
||||||
|
*
|
||||||
|
* Determine primary name based on a list of registered names.
|
||||||
|
*
|
||||||
|
* @param confirmationStatus the status of the transactions for this determination
|
||||||
|
*
|
||||||
|
* @return the primary name, empty if there is no primary name
|
||||||
|
*
|
||||||
|
* @throws DataException
|
||||||
|
*/
|
||||||
|
public Optional<String> determinePrimaryName(TransactionsResource.ConfirmationStatus confirmationStatus) throws DataException {
|
||||||
|
|
||||||
|
// all registered names for the owner
|
||||||
|
List<NameData> names = this.repository.getNameRepository().getNamesByOwner(this.address);
|
||||||
|
|
||||||
|
Optional<String> primaryName;
|
||||||
|
|
||||||
|
// if no registered names, the no primary name possible
|
||||||
|
if (names.isEmpty()) {
|
||||||
|
primaryName = Optional.empty();
|
||||||
|
}
|
||||||
|
// if names
|
||||||
|
else {
|
||||||
|
// if one name, then that is the primary name
|
||||||
|
if (names.size() == 1) {
|
||||||
|
primaryName = Optional.of( names.get(0).getName() );
|
||||||
|
}
|
||||||
|
// if more than one name, then seek the earliest name acquisition that was never released
|
||||||
|
else {
|
||||||
|
Map<String, TransactionData> txByName = new HashMap<>(names.size());
|
||||||
|
|
||||||
|
// for each name, get the latest transaction
|
||||||
|
for (NameData nameData : names) {
|
||||||
|
|
||||||
|
// since the name is currently registered to the owner,
|
||||||
|
// we assume the latest transaction involving this name was the transaction that the acquired
|
||||||
|
// name through registration, purchase or update
|
||||||
|
Optional<TransactionData> latestTransaction
|
||||||
|
= this.repository
|
||||||
|
.getTransactionRepository()
|
||||||
|
.getTransactionsInvolvingName(
|
||||||
|
nameData.getName(),
|
||||||
|
confirmationStatus
|
||||||
|
)
|
||||||
|
.stream()
|
||||||
|
.sorted(Comparator.comparing(
|
||||||
|
TransactionData::getTimestamp).reversed()
|
||||||
|
)
|
||||||
|
.findFirst(); // first is the last, since it was reversed
|
||||||
|
|
||||||
|
// if there is a latest transaction, expected for all registered names
|
||||||
|
if (latestTransaction.isPresent()) {
|
||||||
|
txByName.put(nameData.getName(), latestTransaction.get());
|
||||||
|
}
|
||||||
|
// if there is no latest transaction, then
|
||||||
|
else {
|
||||||
|
LOGGER.warn("No matching transaction for name: " + nameData.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the first name aqcuistion for this address
|
||||||
|
Optional<Map.Entry<String, TransactionData>> firstNameEntry
|
||||||
|
= txByName.entrySet().stream().sorted(Comparator.comparing(entry -> entry.getValue().getTimestamp())).findFirst();
|
||||||
|
|
||||||
|
// if their is a name acquisition, then the first one is the primary name
|
||||||
|
if (firstNameEntry.isPresent()) {
|
||||||
|
primaryName = Optional.of( firstNameEntry.get().getKey() );
|
||||||
|
}
|
||||||
|
// if there is no nameacquistion, then there is no primary name
|
||||||
|
else {
|
||||||
|
primaryName = Optional.empty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return primaryName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set Primary Name
|
||||||
|
*
|
||||||
|
* @param primaryName the primary to set to this address
|
||||||
|
*
|
||||||
|
* @return the primary name if successful, empty if unsuccessful
|
||||||
|
*
|
||||||
|
* @throws DataException
|
||||||
|
*/
|
||||||
|
public Optional<String> setPrimaryName( String primaryName ) throws DataException {
|
||||||
|
int changed = this.repository.getNameRepository().setPrimaryName(this.address, primaryName);
|
||||||
|
|
||||||
|
return changed > 0 ? Optional.of(primaryName) : Optional.empty();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns reward-share minting address, or unknown if reward-share does not exist.
|
* Returns reward-share minting address, or unknown if reward-share does not exist.
|
||||||
*
|
*
|
||||||
|
@@ -33,6 +33,7 @@ import javax.ws.rs.*;
|
|||||||
import javax.ws.rs.core.Context;
|
import javax.ws.rs.core.Context;
|
||||||
import javax.ws.rs.core.MediaType;
|
import javax.ws.rs.core.MediaType;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@Path("/names")
|
@Path("/names")
|
||||||
@@ -104,6 +105,45 @@ public class NamesResource {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GET
|
||||||
|
@Path("/primary/{address}")
|
||||||
|
@Operation(
|
||||||
|
summary = "primary name owned by address",
|
||||||
|
responses = {
|
||||||
|
@ApiResponse(
|
||||||
|
description = "registered primary name info",
|
||||||
|
content = @Content(
|
||||||
|
mediaType = MediaType.APPLICATION_JSON,
|
||||||
|
schema = @Schema(implementation = NameSummary.class)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
@ApiErrors({ApiError.INVALID_ADDRESS, ApiError.REPOSITORY_ISSUE, ApiError.UNAUTHORIZED})
|
||||||
|
public NameSummary getPrimaryNameByAddress(@PathParam("address") String address) {
|
||||||
|
if (!Crypto.isValidAddress(address))
|
||||||
|
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_ADDRESS);
|
||||||
|
|
||||||
|
try (final Repository repository = RepositoryManager.getRepository()) {
|
||||||
|
|
||||||
|
if (Settings.getInstance().isLite()) {
|
||||||
|
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.UNAUTHORIZED);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Optional<String> primaryName = repository.getNameRepository().getPrimaryName(address);
|
||||||
|
|
||||||
|
if(primaryName.isPresent()) {
|
||||||
|
return new NameSummary(new NameData(primaryName.get(), address));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return new NameSummary((new NameData(null, address)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (DataException e) {
|
||||||
|
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
@Path("/{name}")
|
@Path("/{name}")
|
||||||
@Operation(
|
@Operation(
|
||||||
|
@@ -1640,6 +1640,8 @@ public class Block {
|
|||||||
SelfSponsorshipAlgoV2Block.processAccountPenalties(this);
|
SelfSponsorshipAlgoV2Block.processAccountPenalties(this);
|
||||||
} else if (this.blockData.getHeight() == BlockChain.getInstance().getSelfSponsorshipAlgoV3Height()) {
|
} else if (this.blockData.getHeight() == BlockChain.getInstance().getSelfSponsorshipAlgoV3Height()) {
|
||||||
SelfSponsorshipAlgoV3Block.processAccountPenalties(this);
|
SelfSponsorshipAlgoV3Block.processAccountPenalties(this);
|
||||||
|
} else if (this.blockData.getHeight() == BlockChain.getInstance().getMultipleNamesPerAccountHeight()) {
|
||||||
|
PrimaryNamesBlock.processNames(this.repository);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1952,6 +1954,8 @@ public class Block {
|
|||||||
SelfSponsorshipAlgoV2Block.orphanAccountPenalties(this);
|
SelfSponsorshipAlgoV2Block.orphanAccountPenalties(this);
|
||||||
} else if (this.blockData.getHeight() == BlockChain.getInstance().getSelfSponsorshipAlgoV3Height()) {
|
} else if (this.blockData.getHeight() == BlockChain.getInstance().getSelfSponsorshipAlgoV3Height()) {
|
||||||
SelfSponsorshipAlgoV3Block.orphanAccountPenalties(this);
|
SelfSponsorshipAlgoV3Block.orphanAccountPenalties(this);
|
||||||
|
} else if (this.blockData.getHeight() == BlockChain.getInstance().getMultipleNamesPerAccountHeight()) {
|
||||||
|
PrimaryNamesBlock.orphanNames( this.repository );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
47
src/main/java/org/qortal/block/PrimaryNamesBlock.java
Normal file
47
src/main/java/org/qortal/block/PrimaryNamesBlock.java
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
package org.qortal.block;
|
||||||
|
|
||||||
|
import org.qortal.account.Account;
|
||||||
|
import org.qortal.api.resource.TransactionsResource;
|
||||||
|
import org.qortal.data.naming.NameData;
|
||||||
|
import org.qortal.repository.DataException;
|
||||||
|
import org.qortal.repository.Repository;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class PrimaryNamesBlock
|
||||||
|
*/
|
||||||
|
public class PrimaryNamesBlock {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process Primary Names
|
||||||
|
*
|
||||||
|
* @param repository
|
||||||
|
* @throws DataException
|
||||||
|
*/
|
||||||
|
public static void processNames(Repository repository) throws DataException {
|
||||||
|
|
||||||
|
Set<String> addressesWithNames
|
||||||
|
= repository.getNameRepository().getAllNames().stream()
|
||||||
|
.map(NameData::getOwner).collect(Collectors.toSet());
|
||||||
|
|
||||||
|
// for each address with a name, set primary name to the address
|
||||||
|
for( String address : addressesWithNames ) {
|
||||||
|
|
||||||
|
Account account = new Account(repository, address);
|
||||||
|
account.resetPrimaryName(TransactionsResource.ConfirmationStatus.CONFIRMED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Orphan the Primary Names Block
|
||||||
|
*
|
||||||
|
* @param repository
|
||||||
|
* @throws DataException
|
||||||
|
*/
|
||||||
|
public static void orphanNames(Repository repository) throws DataException {
|
||||||
|
|
||||||
|
repository.getNameRepository().clearPrimaryNames();
|
||||||
|
}
|
||||||
|
}
|
@@ -67,6 +67,11 @@ public class NameData {
|
|||||||
this(name, reducedName, owner, data, registered, null, false, null, reference, creationGroupId);
|
this(name, reducedName, owner, data, registered, null, false, null, reference, creationGroupId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Typically used for name summsry
|
||||||
|
public NameData(String name, String owner) {
|
||||||
|
this(name, null, owner, null, 0L, null, false, null, null, 0);
|
||||||
|
}
|
||||||
|
|
||||||
// Getters / setters
|
// Getters / setters
|
||||||
|
|
||||||
public String getName() {
|
public String getName() {
|
||||||
|
@@ -3,6 +3,7 @@ package org.qortal.repository;
|
|||||||
import org.qortal.data.naming.NameData;
|
import org.qortal.data.naming.NameData;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
public interface NameRepository {
|
public interface NameRepository {
|
||||||
|
|
||||||
@@ -34,10 +35,17 @@ public interface NameRepository {
|
|||||||
return getNamesByOwner(address, null, null, null);
|
return getNamesByOwner(address, null, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int setPrimaryName(String address, String primaryName) throws DataException;
|
||||||
|
|
||||||
|
public void removePrimaryName(String address) throws DataException;
|
||||||
|
|
||||||
|
public Optional<String> getPrimaryName(String address) throws DataException;
|
||||||
|
|
||||||
|
public int clearPrimaryNames() throws DataException;
|
||||||
|
|
||||||
public List<String> getRecentNames(long startTimestamp) throws DataException;
|
public List<String> getRecentNames(long startTimestamp) throws DataException;
|
||||||
|
|
||||||
public void save(NameData nameData) throws DataException;
|
public void save(NameData nameData) throws DataException;
|
||||||
|
|
||||||
public void delete(String name) throws DataException;
|
public void delete(String name) throws DataException;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -1,5 +1,8 @@
|
|||||||
package org.qortal.repository.hsqldb;
|
package org.qortal.repository.hsqldb;
|
||||||
|
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
|
import org.qortal.block.BlockChain;
|
||||||
import org.qortal.data.chat.ActiveChats;
|
import org.qortal.data.chat.ActiveChats;
|
||||||
import org.qortal.data.chat.ActiveChats.DirectChat;
|
import org.qortal.data.chat.ActiveChats.DirectChat;
|
||||||
import org.qortal.data.chat.ActiveChats.GroupChat;
|
import org.qortal.data.chat.ActiveChats.GroupChat;
|
||||||
@@ -18,6 +21,8 @@ import static org.qortal.data.chat.ChatMessage.Encoding;
|
|||||||
|
|
||||||
public class HSQLDBChatRepository implements ChatRepository {
|
public class HSQLDBChatRepository implements ChatRepository {
|
||||||
|
|
||||||
|
private static final Logger LOGGER = LogManager.getLogger(HSQLDBChatRepository.class);
|
||||||
|
|
||||||
protected HSQLDBRepository repository;
|
protected HSQLDBRepository repository;
|
||||||
|
|
||||||
public HSQLDBChatRepository(HSQLDBRepository repository) {
|
public HSQLDBChatRepository(HSQLDBRepository repository) {
|
||||||
@@ -142,10 +147,23 @@ public class HSQLDBChatRepository implements ChatRepository {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ChatMessage toChatMessage(ChatTransactionData chatTransactionData, Encoding encoding) throws DataException {
|
public ChatMessage toChatMessage(ChatTransactionData chatTransactionData, Encoding encoding) throws DataException {
|
||||||
|
|
||||||
|
String tableName;
|
||||||
|
|
||||||
|
// if the PrimaryTable is available, then use it
|
||||||
|
if( this.repository.getBlockRepository().getBlockchainHeight() > BlockChain.getInstance().getMultipleNamesPerAccountHeight()) {
|
||||||
|
LOGGER.info("using PrimaryNames for chat transactions");
|
||||||
|
tableName = "PrimaryNames";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
LOGGER.info("using Names for chat transactions");
|
||||||
|
tableName = "Names";
|
||||||
|
}
|
||||||
|
|
||||||
String sql = "SELECT SenderNames.name, RecipientNames.name "
|
String sql = "SELECT SenderNames.name, RecipientNames.name "
|
||||||
+ "FROM ChatTransactions "
|
+ "FROM ChatTransactions "
|
||||||
+ "LEFT OUTER JOIN Names AS SenderNames ON SenderNames.owner = sender "
|
+ "LEFT OUTER JOIN " + tableName + " AS SenderNames ON SenderNames.owner = sender "
|
||||||
+ "LEFT OUTER JOIN Names AS RecipientNames ON RecipientNames.owner = recipient "
|
+ "LEFT OUTER JOIN " + tableName + " AS RecipientNames ON RecipientNames.owner = recipient "
|
||||||
+ "WHERE signature = ?";
|
+ "WHERE signature = ?";
|
||||||
|
|
||||||
try (ResultSet resultSet = this.repository.checkedExecute(sql, chatTransactionData.getSignature())) {
|
try (ResultSet resultSet = this.repository.checkedExecute(sql, chatTransactionData.getSignature())) {
|
||||||
|
@@ -1053,6 +1053,12 @@ public class HSQLDBDatabaseUpdates {
|
|||||||
stmt.execute("UPDATE Accounts SET blocks_minted_penalty = -5000000 WHERE blocks_minted_penalty < 0");
|
stmt.execute("UPDATE Accounts SET blocks_minted_penalty = -5000000 WHERE blocks_minted_penalty < 0");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 50:
|
||||||
|
// Primary name for a Qortal Address, 0-1 for any address
|
||||||
|
stmt.execute("CREATE TABLE PrimaryNames (owner QortalAddress, name RegisteredName, "
|
||||||
|
+ "PRIMARY KEY (owner), FOREIGN KEY (name) REFERENCES Names (name) ON DELETE CASCADE)");
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
// nothing to do
|
// nothing to do
|
||||||
return false;
|
return false;
|
||||||
|
@@ -8,6 +8,7 @@ import java.sql.ResultSet;
|
|||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
public class HSQLDBNameRepository implements NameRepository {
|
public class HSQLDBNameRepository implements NameRepository {
|
||||||
|
|
||||||
@@ -333,6 +334,55 @@ public class HSQLDBNameRepository implements NameRepository {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removePrimaryName(String address) throws DataException {
|
||||||
|
try {
|
||||||
|
this.repository.delete("PrimaryNames", "owner = ?", address);
|
||||||
|
} catch (SQLException e) {
|
||||||
|
throw new DataException("Unable to delete primary name from repository", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<String> getPrimaryName(String address) throws DataException {
|
||||||
|
String sql = "SELECT name FROM PrimaryNames WHERE owner = ?";
|
||||||
|
|
||||||
|
List<String> names = new ArrayList<>();
|
||||||
|
|
||||||
|
try (ResultSet resultSet = this.repository.checkedExecute(sql, address)) {
|
||||||
|
if (resultSet == null)
|
||||||
|
return Optional.empty();
|
||||||
|
|
||||||
|
String name = resultSet.getString(1);
|
||||||
|
|
||||||
|
return Optional.of(name);
|
||||||
|
} catch (SQLException e) {
|
||||||
|
throw new DataException("Unable to fetch recent names from repository", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int setPrimaryName(String address, String primaryName) throws DataException {
|
||||||
|
|
||||||
|
String sql = "INSERT INTO PrimaryNames (owner, name) VALUES (?, ?) ON DUPLICATE KEY UPDATE name = ?";
|
||||||
|
|
||||||
|
try{
|
||||||
|
return this.repository.executeCheckedUpdate(sql, address, primaryName, primaryName);
|
||||||
|
} catch (SQLException e) {
|
||||||
|
throw new DataException("Unable to set primary name", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int clearPrimaryNames() throws DataException {
|
||||||
|
|
||||||
|
try {
|
||||||
|
return this.repository.delete("PrimaryNames");
|
||||||
|
} catch (SQLException e) {
|
||||||
|
throw new DataException("Unable to clear primary names from repository", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void save(NameData nameData) throws DataException {
|
public void save(NameData nameData) throws DataException {
|
||||||
HSQLDBSaver saveHelper = new HSQLDBSaver("Names");
|
HSQLDBSaver saveHelper = new HSQLDBSaver("Names");
|
||||||
|
@@ -16,6 +16,7 @@ import org.qortal.utils.Unicode;
|
|||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
public class BuyNameTransaction extends Transaction {
|
public class BuyNameTransaction extends Transaction {
|
||||||
|
|
||||||
@@ -117,6 +118,25 @@ public class BuyNameTransaction extends Transaction {
|
|||||||
|
|
||||||
// Save transaction with updated "name reference" pointing to previous transaction that changed name
|
// Save transaction with updated "name reference" pointing to previous transaction that changed name
|
||||||
this.repository.getTransactionRepository().save(this.buyNameTransactionData);
|
this.repository.getTransactionRepository().save(this.buyNameTransactionData);
|
||||||
|
|
||||||
|
// if multiple names feature is activated, then check the buyer and seller's primary name status
|
||||||
|
if( this.repository.getBlockRepository().getBlockchainHeight() > BlockChain.getInstance().getMultipleNamesPerAccountHeight()) {
|
||||||
|
|
||||||
|
Account seller = new Account(this.repository, this.buyNameTransactionData.getSeller());
|
||||||
|
Optional<String> sellerPrimaryName = seller.getPrimaryName();
|
||||||
|
|
||||||
|
// if the seller sold their primary name, then remove their primary name
|
||||||
|
if (sellerPrimaryName.isPresent() && sellerPrimaryName.get().equals(buyNameTransactionData.getName())) {
|
||||||
|
seller.removePrimaryName();
|
||||||
|
}
|
||||||
|
|
||||||
|
Account buyer = new Account(this.repository, this.getBuyer().getAddress());
|
||||||
|
|
||||||
|
// if the buyer had no primary name, then set the primary name to the name bought
|
||||||
|
if( buyer.getPrimaryName().isEmpty() ) {
|
||||||
|
buyer.setPrimaryName(this.buyNameTransactionData.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -127,6 +147,24 @@ public class BuyNameTransaction extends Transaction {
|
|||||||
|
|
||||||
// Save this transaction, with previous "name reference"
|
// Save this transaction, with previous "name reference"
|
||||||
this.repository.getTransactionRepository().save(this.buyNameTransactionData);
|
this.repository.getTransactionRepository().save(this.buyNameTransactionData);
|
||||||
}
|
|
||||||
|
|
||||||
|
// if multiple names feature is activated, then check the buyer and seller's primary name status
|
||||||
|
if( this.repository.getBlockRepository().getBlockchainHeight() > BlockChain.getInstance().getMultipleNamesPerAccountHeight()) {
|
||||||
|
|
||||||
|
Account seller = new Account(this.repository, this.buyNameTransactionData.getSeller());
|
||||||
|
|
||||||
|
// if the seller lost their primary name, then set their primary name back
|
||||||
|
if (seller.getPrimaryName().isEmpty()) {
|
||||||
|
seller.setPrimaryName(this.buyNameTransactionData.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
Account buyer = new Account(this.repository, this.getBuyer().getAddress());
|
||||||
|
Optional<String> buyerPrimaryName = buyer.getPrimaryName();
|
||||||
|
|
||||||
|
// if the buyer bought their primary, then remove it
|
||||||
|
if( buyerPrimaryName.isPresent() && this.buyNameTransactionData.getName().equals(buyerPrimaryName.get()) ) {
|
||||||
|
buyer.removePrimaryName();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -2,10 +2,12 @@ package org.qortal.transaction;
|
|||||||
|
|
||||||
import com.google.common.base.Utf8;
|
import com.google.common.base.Utf8;
|
||||||
import org.qortal.account.Account;
|
import org.qortal.account.Account;
|
||||||
|
import org.qortal.api.resource.TransactionsResource;
|
||||||
import org.qortal.asset.Asset;
|
import org.qortal.asset.Asset;
|
||||||
import org.qortal.block.BlockChain;
|
import org.qortal.block.BlockChain;
|
||||||
import org.qortal.controller.repository.NamesDatabaseIntegrityCheck;
|
import org.qortal.controller.repository.NamesDatabaseIntegrityCheck;
|
||||||
import org.qortal.crypto.Crypto;
|
import org.qortal.crypto.Crypto;
|
||||||
|
import org.qortal.data.naming.NameData;
|
||||||
import org.qortal.data.transaction.RegisterNameTransactionData;
|
import org.qortal.data.transaction.RegisterNameTransactionData;
|
||||||
import org.qortal.data.transaction.TransactionData;
|
import org.qortal.data.transaction.TransactionData;
|
||||||
import org.qortal.naming.Name;
|
import org.qortal.naming.Name;
|
||||||
@@ -15,6 +17,7 @@ import org.qortal.utils.Unicode;
|
|||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
public class RegisterNameTransaction extends Transaction {
|
public class RegisterNameTransaction extends Transaction {
|
||||||
|
|
||||||
@@ -54,6 +57,15 @@ public class RegisterNameTransaction extends Transaction {
|
|||||||
Account registrant = getRegistrant();
|
Account registrant = getRegistrant();
|
||||||
String name = this.registerNameTransactionData.getName();
|
String name = this.registerNameTransactionData.getName();
|
||||||
|
|
||||||
|
Optional<String> registrantPrimaryName = registrant.getPrimaryName();
|
||||||
|
if( registrantPrimaryName.isPresent() ) {
|
||||||
|
|
||||||
|
NameData nameData = repository.getNameRepository().fromName(registrantPrimaryName.get());
|
||||||
|
if (nameData.isForSale()) {
|
||||||
|
return ValidationResult.NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int blockchainHeight = this.repository.getBlockRepository().getBlockchainHeight();
|
int blockchainHeight = this.repository.getBlockRepository().getBlockchainHeight();
|
||||||
final int start = BlockChain.getInstance().getSelfSponsorshipAlgoV2Height() - 1180;
|
final int start = BlockChain.getInstance().getSelfSponsorshipAlgoV2Height() - 1180;
|
||||||
final int end = BlockChain.getInstance().getSelfSponsorshipAlgoV3Height();
|
final int end = BlockChain.getInstance().getSelfSponsorshipAlgoV3Height();
|
||||||
@@ -117,6 +129,16 @@ public class RegisterNameTransaction extends Transaction {
|
|||||||
// Register Name
|
// Register Name
|
||||||
Name name = new Name(this.repository, this.registerNameTransactionData);
|
Name name = new Name(this.repository, this.registerNameTransactionData);
|
||||||
name.register();
|
name.register();
|
||||||
|
|
||||||
|
if( this.repository.getBlockRepository().getBlockchainHeight() > BlockChain.getInstance().getMultipleNamesPerAccountHeight()) {
|
||||||
|
|
||||||
|
Account account = new Account(this.repository, this.getCreator().getAddress());
|
||||||
|
|
||||||
|
// if there is no primary name established, then the new registered name is the primary name
|
||||||
|
if (account.getPrimaryName().isEmpty()) {
|
||||||
|
account.setPrimaryName(this.registerNameTransactionData.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@@ -3,6 +3,7 @@ package org.qortal.transaction;
|
|||||||
import com.google.common.base.Utf8;
|
import com.google.common.base.Utf8;
|
||||||
import org.qortal.account.Account;
|
import org.qortal.account.Account;
|
||||||
import org.qortal.asset.Asset;
|
import org.qortal.asset.Asset;
|
||||||
|
import org.qortal.block.BlockChain;
|
||||||
import org.qortal.controller.repository.NamesDatabaseIntegrityCheck;
|
import org.qortal.controller.repository.NamesDatabaseIntegrityCheck;
|
||||||
import org.qortal.crypto.Crypto;
|
import org.qortal.crypto.Crypto;
|
||||||
import org.qortal.data.naming.NameData;
|
import org.qortal.data.naming.NameData;
|
||||||
@@ -49,6 +50,12 @@ public class UpdateNameTransaction extends Transaction {
|
|||||||
public ValidationResult isValid() throws DataException {
|
public ValidationResult isValid() throws DataException {
|
||||||
String name = this.updateNameTransactionData.getName();
|
String name = this.updateNameTransactionData.getName();
|
||||||
|
|
||||||
|
// if the account has more than one name, then they cannot update their primary name
|
||||||
|
if( this.repository.getNameRepository().getNamesByOwner(this.getOwner().getAddress()).size() > 1 &&
|
||||||
|
this.getOwner().getPrimaryName().get().equals(name) ) {
|
||||||
|
return ValidationResult.NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
// Check name size bounds
|
// Check name size bounds
|
||||||
int nameLength = Utf8.encodedLength(name);
|
int nameLength = Utf8.encodedLength(name);
|
||||||
if (nameLength < Name.MIN_NAME_SIZE || nameLength > Name.MAX_NAME_SIZE)
|
if (nameLength < Name.MIN_NAME_SIZE || nameLength > Name.MAX_NAME_SIZE)
|
||||||
@@ -152,6 +159,16 @@ public class UpdateNameTransaction extends Transaction {
|
|||||||
|
|
||||||
// Save this transaction, now with updated "name reference" to previous transaction that changed name
|
// Save this transaction, now with updated "name reference" to previous transaction that changed name
|
||||||
this.repository.getTransactionRepository().save(this.updateNameTransactionData);
|
this.repository.getTransactionRepository().save(this.updateNameTransactionData);
|
||||||
|
|
||||||
|
if( this.repository.getBlockRepository().getBlockchainHeight() > BlockChain.getInstance().getMultipleNamesPerAccountHeight()) {
|
||||||
|
|
||||||
|
Account account = new Account(this.repository, this.getCreator().getAddress());
|
||||||
|
|
||||||
|
// if updating the primary name, then set primary name to new name
|
||||||
|
if( account.getPrimaryName().isEmpty() || account.getPrimaryName().get().equals(this.updateNameTransactionData.getName())) {
|
||||||
|
account.setPrimaryName(this.updateNameTransactionData.getNewName());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -167,6 +184,16 @@ public class UpdateNameTransaction extends Transaction {
|
|||||||
|
|
||||||
// Save this transaction, with previous "name reference"
|
// Save this transaction, with previous "name reference"
|
||||||
this.repository.getTransactionRepository().save(this.updateNameTransactionData);
|
this.repository.getTransactionRepository().save(this.updateNameTransactionData);
|
||||||
|
|
||||||
|
if( this.repository.getBlockRepository().getBlockchainHeight() > BlockChain.getInstance().getMultipleNamesPerAccountHeight()) {
|
||||||
|
|
||||||
|
Account account = new Account(this.repository, this.getCreator().getAddress());
|
||||||
|
|
||||||
|
// if the primary name is the new updated name, then it needs to be set back to the previous name
|
||||||
|
if (account.getPrimaryName().isPresent() && account.getPrimaryName().get().equals(this.updateNameTransactionData.getNewName())) {
|
||||||
|
account.setPrimaryName(this.updateNameTransactionData.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -4,6 +4,7 @@ import org.junit.After;
|
|||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.qortal.account.PrivateKeyAccount;
|
import org.qortal.account.PrivateKeyAccount;
|
||||||
|
import org.qortal.api.resource.TransactionsResource;
|
||||||
import org.qortal.block.BlockChain;
|
import org.qortal.block.BlockChain;
|
||||||
import org.qortal.data.naming.NameData;
|
import org.qortal.data.naming.NameData;
|
||||||
import org.qortal.data.transaction.BuyNameTransactionData;
|
import org.qortal.data.transaction.BuyNameTransactionData;
|
||||||
@@ -22,6 +23,7 @@ import org.qortal.transaction.Transaction;
|
|||||||
import org.qortal.utils.Amounts;
|
import org.qortal.utils.Amounts;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
@@ -135,13 +137,26 @@ public class BuySellTests extends Common {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSellName() throws DataException {
|
public void testSellName() throws DataException {
|
||||||
|
// mint passed the feature trigger block
|
||||||
|
BlockUtils.mintBlocks(repository, BlockChain.getInstance().getMultipleNamesPerAccountHeight());
|
||||||
|
|
||||||
// Register-name
|
// Register-name
|
||||||
testRegisterName();
|
testRegisterName();
|
||||||
|
|
||||||
|
// assert primary name for alice
|
||||||
|
Optional<String> alicePrimaryName1 = alice.getPrimaryName();
|
||||||
|
assertTrue(alicePrimaryName1.isPresent());
|
||||||
|
assertTrue(alicePrimaryName1.get().equals(name));
|
||||||
|
|
||||||
// Sell-name
|
// Sell-name
|
||||||
SellNameTransactionData transactionData = new SellNameTransactionData(TestTransaction.generateBase(alice), name, price);
|
SellNameTransactionData transactionData = new SellNameTransactionData(TestTransaction.generateBase(alice), name, price);
|
||||||
TransactionUtils.signAndMint(repository, transactionData, alice);
|
TransactionUtils.signAndMint(repository, transactionData, alice);
|
||||||
|
|
||||||
|
// assert primary name for alice
|
||||||
|
Optional<String> alicePrimaryName2 = alice.getPrimaryName();
|
||||||
|
assertTrue(alicePrimaryName2.isPresent());
|
||||||
|
assertTrue(alicePrimaryName2.get().equals(name));
|
||||||
|
|
||||||
NameData nameData;
|
NameData nameData;
|
||||||
|
|
||||||
// Check name is for sale
|
// Check name is for sale
|
||||||
@@ -149,6 +164,14 @@ public class BuySellTests extends Common {
|
|||||||
assertTrue(nameData.isForSale());
|
assertTrue(nameData.isForSale());
|
||||||
assertEquals("price incorrect", price, nameData.getSalePrice());
|
assertEquals("price incorrect", price, nameData.getSalePrice());
|
||||||
|
|
||||||
|
// assert alice cannot register another name while primary name is for sale
|
||||||
|
final String name2 = "another name";
|
||||||
|
RegisterNameTransactionData registerSecondNameData = new RegisterNameTransactionData(TestTransaction.generateBase(alice), name2, "{}");
|
||||||
|
Transaction.ValidationResult registrationResult = TransactionUtils.signAndImport(repository, registerSecondNameData, alice);
|
||||||
|
|
||||||
|
// check that registering is not supported while primary name is for sale
|
||||||
|
assertTrue(Transaction.ValidationResult.NOT_SUPPORTED.equals(registrationResult));
|
||||||
|
|
||||||
// Orphan sell-name
|
// Orphan sell-name
|
||||||
BlockUtils.orphanLastBlock(repository);
|
BlockUtils.orphanLastBlock(repository);
|
||||||
|
|
||||||
@@ -168,6 +191,10 @@ public class BuySellTests extends Common {
|
|||||||
// Orphan sell-name and register-name
|
// Orphan sell-name and register-name
|
||||||
BlockUtils.orphanBlocks(repository, 2);
|
BlockUtils.orphanBlocks(repository, 2);
|
||||||
|
|
||||||
|
// assert primary name for alice
|
||||||
|
Optional<String> alicePrimaryName3 = alice.getPrimaryName();
|
||||||
|
assertTrue(alicePrimaryName3.isEmpty());
|
||||||
|
|
||||||
// Check name no longer exists
|
// Check name no longer exists
|
||||||
assertFalse(repository.getNameRepository().nameExists(name));
|
assertFalse(repository.getNameRepository().nameExists(name));
|
||||||
nameData = repository.getNameRepository().fromName(name);
|
nameData = repository.getNameRepository().fromName(name);
|
||||||
@@ -261,15 +288,36 @@ public class BuySellTests extends Common {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testBuyName() throws DataException {
|
public void testBuyName() throws DataException {
|
||||||
|
// move passed primary initiation
|
||||||
|
BlockUtils.mintBlocks(repository, BlockChain.getInstance().getMultipleNamesPerAccountHeight());
|
||||||
|
|
||||||
// Register-name and sell-name
|
// Register-name and sell-name
|
||||||
testSellName();
|
testSellName();
|
||||||
|
|
||||||
String seller = alice.getAddress();
|
String seller = alice.getAddress();
|
||||||
|
|
||||||
|
// assert alice has the name as primary
|
||||||
|
Optional<String> alicePrimaryName1 = alice.getPrimaryName();
|
||||||
|
assertTrue(alicePrimaryName1.isPresent());
|
||||||
|
assertEquals(name, alicePrimaryName1.get());
|
||||||
|
|
||||||
|
// assert bob does not have a primary name
|
||||||
|
Optional<String> bobPrimaryName1 = bob.getPrimaryName();
|
||||||
|
assertTrue(bobPrimaryName1.isEmpty());
|
||||||
|
|
||||||
// Buy-name
|
// Buy-name
|
||||||
BuyNameTransactionData transactionData = new BuyNameTransactionData(TestTransaction.generateBase(bob), name, price, seller);
|
BuyNameTransactionData transactionData = new BuyNameTransactionData(TestTransaction.generateBase(bob), name, price, seller);
|
||||||
TransactionUtils.signAndMint(repository, transactionData, bob);
|
TransactionUtils.signAndMint(repository, transactionData, bob);
|
||||||
|
|
||||||
|
// assert alice does not have a primary name anymore
|
||||||
|
Optional<String> alicePrimaryName2 = alice.getPrimaryName();
|
||||||
|
assertTrue(alicePrimaryName2.isEmpty());
|
||||||
|
|
||||||
|
// assert bob does have the name as primary
|
||||||
|
Optional<String> bobPrimaryName2 = bob.getPrimaryName();
|
||||||
|
assertTrue(bobPrimaryName2.isPresent());
|
||||||
|
assertEquals(name, bobPrimaryName2.get());
|
||||||
|
|
||||||
NameData nameData;
|
NameData nameData;
|
||||||
|
|
||||||
// Check name is sold
|
// Check name is sold
|
||||||
@@ -280,6 +328,15 @@ public class BuySellTests extends Common {
|
|||||||
// Orphan buy-name
|
// Orphan buy-name
|
||||||
BlockUtils.orphanLastBlock(repository);
|
BlockUtils.orphanLastBlock(repository);
|
||||||
|
|
||||||
|
// assert alice has the name as primary
|
||||||
|
Optional<String> alicePrimaryNameOrphaned = alice.getPrimaryName();
|
||||||
|
assertTrue(alicePrimaryNameOrphaned.isPresent());
|
||||||
|
assertEquals(name, alicePrimaryNameOrphaned.get());
|
||||||
|
|
||||||
|
// assert bob does not have a primary name
|
||||||
|
Optional<String> bobPrimaryNameOrphaned = bob.getPrimaryName();
|
||||||
|
assertTrue(bobPrimaryNameOrphaned.isEmpty());
|
||||||
|
|
||||||
// Check name is for sale (not sold)
|
// Check name is for sale (not sold)
|
||||||
nameData = repository.getNameRepository().fromName(name);
|
nameData = repository.getNameRepository().fromName(name);
|
||||||
assertTrue(nameData.isForSale());
|
assertTrue(nameData.isForSale());
|
||||||
@@ -314,6 +371,9 @@ public class BuySellTests extends Common {
|
|||||||
assertFalse(nameData.isForSale());
|
assertFalse(nameData.isForSale());
|
||||||
// Not concerned about price
|
// Not concerned about price
|
||||||
assertEquals(bob.getAddress(), nameData.getOwner());
|
assertEquals(bob.getAddress(), nameData.getOwner());
|
||||||
|
|
||||||
|
assertEquals(alice.getPrimaryName(), alice.determinePrimaryName(TransactionsResource.ConfirmationStatus.CONFIRMED));
|
||||||
|
assertEquals(bob.getPrimaryName(), bob.determinePrimaryName(TransactionsResource.ConfirmationStatus.CONFIRMED));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -373,6 +433,9 @@ public class BuySellTests extends Common {
|
|||||||
assertTrue(nameData.isForSale());
|
assertTrue(nameData.isForSale());
|
||||||
assertEquals("price incorrect", newPrice, nameData.getSalePrice());
|
assertEquals("price incorrect", newPrice, nameData.getSalePrice());
|
||||||
assertEquals(bob.getAddress(), nameData.getOwner());
|
assertEquals(bob.getAddress(), nameData.getOwner());
|
||||||
|
|
||||||
|
assertEquals(alice.getPrimaryName(), alice.determinePrimaryName(TransactionsResource.ConfirmationStatus.CONFIRMED));
|
||||||
|
assertEquals(bob.getPrimaryName(), bob.determinePrimaryName(TransactionsResource.ConfirmationStatus.CONFIRMED));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -4,6 +4,8 @@ import org.junit.Before;
|
|||||||
import org.junit.Ignore;
|
import org.junit.Ignore;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.qortal.account.PrivateKeyAccount;
|
import org.qortal.account.PrivateKeyAccount;
|
||||||
|
import org.qortal.api.resource.TransactionsResource;
|
||||||
|
import org.qortal.block.BlockChain;
|
||||||
import org.qortal.controller.repository.NamesDatabaseIntegrityCheck;
|
import org.qortal.controller.repository.NamesDatabaseIntegrityCheck;
|
||||||
import org.qortal.data.naming.NameData;
|
import org.qortal.data.naming.NameData;
|
||||||
import org.qortal.data.transaction.*;
|
import org.qortal.data.transaction.*;
|
||||||
@@ -13,6 +15,7 @@ import org.qortal.repository.RepositoryFactory;
|
|||||||
import org.qortal.repository.RepositoryManager;
|
import org.qortal.repository.RepositoryManager;
|
||||||
import org.qortal.repository.hsqldb.HSQLDBRepositoryFactory;
|
import org.qortal.repository.hsqldb.HSQLDBRepositoryFactory;
|
||||||
import org.qortal.settings.Settings;
|
import org.qortal.settings.Settings;
|
||||||
|
import org.qortal.test.common.BlockUtils;
|
||||||
import org.qortal.test.common.Common;
|
import org.qortal.test.common.Common;
|
||||||
import org.qortal.test.common.TransactionUtils;
|
import org.qortal.test.common.TransactionUtils;
|
||||||
import org.qortal.test.common.transaction.TestTransaction;
|
import org.qortal.test.common.transaction.TestTransaction;
|
||||||
@@ -385,6 +388,8 @@ public class IntegrityTests extends Common {
|
|||||||
@Test
|
@Test
|
||||||
public void testUpdateToMissingName() throws DataException {
|
public void testUpdateToMissingName() throws DataException {
|
||||||
try (final Repository repository = RepositoryManager.getRepository()) {
|
try (final Repository repository = RepositoryManager.getRepository()) {
|
||||||
|
BlockUtils.mintBlocks(repository, BlockChain.getInstance().getMultipleNamesPerAccountHeight());
|
||||||
|
|
||||||
// Register-name
|
// Register-name
|
||||||
PrivateKeyAccount alice = Common.getTestAccount(repository, "alice");
|
PrivateKeyAccount alice = Common.getTestAccount(repository, "alice");
|
||||||
String initialName = "test-name";
|
String initialName = "test-name";
|
||||||
@@ -422,7 +427,12 @@ public class IntegrityTests extends Common {
|
|||||||
// Therefore the name that we are trying to rename TO already exists
|
// Therefore the name that we are trying to rename TO already exists
|
||||||
Transaction.ValidationResult result = transaction.importAsUnconfirmed();
|
Transaction.ValidationResult result = transaction.importAsUnconfirmed();
|
||||||
assertTrue("Transaction should be invalid", Transaction.ValidationResult.OK != result);
|
assertTrue("Transaction should be invalid", Transaction.ValidationResult.OK != result);
|
||||||
assertTrue("Destination name should already exist", Transaction.ValidationResult.NAME_ALREADY_REGISTERED == result);
|
|
||||||
|
// this assertion has been updated, because the primary name logic now comes into play and you cannot update a primary name when there
|
||||||
|
// is other names registered and if your try a NOT SUPPORTED result will be given
|
||||||
|
assertTrue("Destination name should already exist", Transaction.ValidationResult.NOT_SUPPORTED == result);
|
||||||
|
|
||||||
|
assertEquals(alice.getPrimaryName(), alice.determinePrimaryName(TransactionsResource.ConfirmationStatus.CONFIRMED));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
package org.qortal.test.naming;
|
package org.qortal.test.naming;
|
||||||
|
|
||||||
import org.apache.commons.lang3.reflect.FieldUtils;
|
import org.apache.commons.lang3.reflect.FieldUtils;
|
||||||
|
import org.junit.Assert;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.qortal.account.PrivateKeyAccount;
|
import org.qortal.account.PrivateKeyAccount;
|
||||||
@@ -8,6 +9,7 @@ import org.qortal.api.AmountTypeAdapter;
|
|||||||
import org.qortal.block.BlockChain;
|
import org.qortal.block.BlockChain;
|
||||||
import org.qortal.block.BlockChain.UnitFeesByTimestamp;
|
import org.qortal.block.BlockChain.UnitFeesByTimestamp;
|
||||||
import org.qortal.controller.BlockMinter;
|
import org.qortal.controller.BlockMinter;
|
||||||
|
import org.qortal.data.naming.NameData;
|
||||||
import org.qortal.data.transaction.PaymentTransactionData;
|
import org.qortal.data.transaction.PaymentTransactionData;
|
||||||
import org.qortal.data.transaction.RegisterNameTransactionData;
|
import org.qortal.data.transaction.RegisterNameTransactionData;
|
||||||
import org.qortal.data.transaction.TransactionData;
|
import org.qortal.data.transaction.TransactionData;
|
||||||
@@ -28,6 +30,7 @@ import org.qortal.utils.NTP;
|
|||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
@@ -121,6 +124,8 @@ public class MiscTests extends Common {
|
|||||||
transactionData.setFee(new RegisterNameTransaction(null, null).getUnitFee(transactionData.getTimestamp()));
|
transactionData.setFee(new RegisterNameTransaction(null, null).getUnitFee(transactionData.getTimestamp()));
|
||||||
TransactionUtils.signAndMint(repository, transactionData, alice);
|
TransactionUtils.signAndMint(repository, transactionData, alice);
|
||||||
|
|
||||||
|
BlockUtils.mintBlocks(repository, BlockChain.getInstance().getMultipleNamesPerAccountHeight());
|
||||||
|
|
||||||
// Register another name that we will later attempt to rename to first name (above)
|
// Register another name that we will later attempt to rename to first name (above)
|
||||||
String otherName = "new-name";
|
String otherName = "new-name";
|
||||||
String otherData = "";
|
String otherData = "";
|
||||||
@@ -335,6 +340,8 @@ public class MiscTests extends Common {
|
|||||||
public void testRegisterNameFeeIncrease() throws Exception {
|
public void testRegisterNameFeeIncrease() throws Exception {
|
||||||
try (final Repository repository = RepositoryManager.getRepository()) {
|
try (final Repository repository = RepositoryManager.getRepository()) {
|
||||||
|
|
||||||
|
BlockUtils.mintBlocks(repository, BlockChain.getInstance().getMultipleNamesPerAccountHeight());
|
||||||
|
|
||||||
// Add original fee to nameRegistrationUnitFees
|
// Add original fee to nameRegistrationUnitFees
|
||||||
UnitFeesByTimestamp originalFee = new UnitFeesByTimestamp();
|
UnitFeesByTimestamp originalFee = new UnitFeesByTimestamp();
|
||||||
originalFee.timestamp = 0L;
|
originalFee.timestamp = 0L;
|
||||||
@@ -517,4 +524,168 @@ public class MiscTests extends Common {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
@Test
|
||||||
|
public void testPrimaryNameEmpty() throws DataException {
|
||||||
|
|
||||||
|
try (final Repository repository = RepositoryManager.getRepository()) {
|
||||||
|
|
||||||
|
PrivateKeyAccount alice = Common.getTestAccount(repository, "alice");
|
||||||
|
|
||||||
|
// mint passed the feature trigger block
|
||||||
|
BlockUtils.mintBlocks(repository, BlockChain.getInstance().getMultipleNamesPerAccountHeight());
|
||||||
|
|
||||||
|
Optional<String> primaryName = repository.getNameRepository().getPrimaryName(alice.getAddress());
|
||||||
|
|
||||||
|
Assert.assertNotNull(primaryName);
|
||||||
|
Assert.assertTrue(primaryName.isEmpty());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPrimaryNameSingle() throws DataException {
|
||||||
|
|
||||||
|
try (final Repository repository = RepositoryManager.getRepository()) {
|
||||||
|
String name = "alice 1";
|
||||||
|
PrivateKeyAccount alice = Common.getTestAccount(repository, "alice");
|
||||||
|
|
||||||
|
// register name 1
|
||||||
|
RegisterNameTransactionData transactionData1 = new RegisterNameTransactionData(TestTransaction.generateBase(alice), name, "{}");
|
||||||
|
transactionData1.setFee(new RegisterNameTransaction(null, null).getUnitFee(transactionData1.getTimestamp()));
|
||||||
|
TransactionUtils.signAndMint(repository, transactionData1, alice);
|
||||||
|
|
||||||
|
String name1 = transactionData1.getName();
|
||||||
|
|
||||||
|
// check name does exist
|
||||||
|
assertTrue(repository.getNameRepository().nameExists(name1));
|
||||||
|
|
||||||
|
|
||||||
|
// mint passed the feature trigger block
|
||||||
|
BlockUtils.mintBlocks(repository, BlockChain.getInstance().getMultipleNamesPerAccountHeight() + 1);
|
||||||
|
|
||||||
|
Optional<String> primaryName = repository.getNameRepository().getPrimaryName(alice.getAddress());
|
||||||
|
|
||||||
|
Assert.assertNotNull(primaryName);
|
||||||
|
Assert.assertTrue(primaryName.isPresent());
|
||||||
|
Assert.assertEquals(name, primaryName.get());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPrimaryNameSingleAfterFeature() throws DataException {
|
||||||
|
|
||||||
|
try (final Repository repository = RepositoryManager.getRepository()) {
|
||||||
|
String name = "alice 1";
|
||||||
|
PrivateKeyAccount alice = Common.getTestAccount(repository, "alice");
|
||||||
|
|
||||||
|
// mint passed the feature trigger block
|
||||||
|
BlockUtils.mintBlocks(repository, BlockChain.getInstance().getMultipleNamesPerAccountHeight());
|
||||||
|
|
||||||
|
// register name 1
|
||||||
|
RegisterNameTransactionData transactionData1 = new RegisterNameTransactionData(TestTransaction.generateBase(alice), name, "{}");
|
||||||
|
transactionData1.setFee(new RegisterNameTransaction(null, null).getUnitFee(transactionData1.getTimestamp()));
|
||||||
|
TransactionUtils.signAndMint(repository, transactionData1, alice);
|
||||||
|
|
||||||
|
String name1 = transactionData1.getName();
|
||||||
|
|
||||||
|
// check name does exist
|
||||||
|
assertTrue(repository.getNameRepository().nameExists(name1));
|
||||||
|
|
||||||
|
|
||||||
|
Optional<String> primaryName = repository.getNameRepository().getPrimaryName(alice.getAddress());
|
||||||
|
|
||||||
|
Assert.assertNotNull(primaryName);
|
||||||
|
Assert.assertTrue(primaryName.isPresent());
|
||||||
|
Assert.assertEquals(name, primaryName.get());
|
||||||
|
|
||||||
|
BlockUtils.orphanLastBlock(repository);
|
||||||
|
|
||||||
|
Optional<String> primaryNameOrpaned = repository.getNameRepository().getPrimaryName(alice.getAddress());
|
||||||
|
|
||||||
|
Assert.assertNotNull(primaryNameOrpaned);
|
||||||
|
Assert.assertTrue(primaryNameOrpaned.isEmpty());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testUpdateNameMultiple() throws DataException {
|
||||||
|
|
||||||
|
try (final Repository repository = RepositoryManager.getRepository()) {
|
||||||
|
String name = "alice 1";
|
||||||
|
PrivateKeyAccount alice = Common.getTestAccount(repository, "alice");
|
||||||
|
|
||||||
|
// register name 1
|
||||||
|
RegisterNameTransactionData transactionData1 = new RegisterNameTransactionData(TestTransaction.generateBase(alice), name, "{}");
|
||||||
|
transactionData1.setFee(new RegisterNameTransaction(null, null).getUnitFee(transactionData1.getTimestamp()));
|
||||||
|
TransactionUtils.signAndMint(repository, transactionData1, alice);
|
||||||
|
|
||||||
|
String name1 = transactionData1.getName();
|
||||||
|
|
||||||
|
// check name does exist
|
||||||
|
assertTrue(repository.getNameRepository().nameExists(name1));
|
||||||
|
|
||||||
|
// register another name, second registered name should fail before the feature trigger
|
||||||
|
final String name2 = "another name";
|
||||||
|
RegisterNameTransactionData transactionData2 = new RegisterNameTransactionData(TestTransaction.generateBase(alice), name2, "{}");
|
||||||
|
Transaction.ValidationResult resultBeforeFeatureTrigger = TransactionUtils.signAndImport(repository, transactionData2, alice);
|
||||||
|
|
||||||
|
// check that that multiple names is forbidden
|
||||||
|
assertTrue(Transaction.ValidationResult.MULTIPLE_NAMES_FORBIDDEN.equals(resultBeforeFeatureTrigger));
|
||||||
|
|
||||||
|
// mint passed the feature trigger block
|
||||||
|
BlockUtils.mintBlocks(repository, BlockChain.getInstance().getMultipleNamesPerAccountHeight());
|
||||||
|
|
||||||
|
// register again, now that we are passed the feature trigger
|
||||||
|
RegisterNameTransactionData transactionData3 = new RegisterNameTransactionData(TestTransaction.generateBase(alice), name2, "{}");
|
||||||
|
Transaction.ValidationResult resultAfterFeatureTrigger = TransactionUtils.signAndImport(repository, transactionData3, alice);
|
||||||
|
|
||||||
|
// check that multiple names is ok
|
||||||
|
assertTrue(Transaction.ValidationResult.OK.equals(resultAfterFeatureTrigger));
|
||||||
|
|
||||||
|
// mint block, confirm transaction
|
||||||
|
BlockUtils.mintBlock(repository);
|
||||||
|
|
||||||
|
// check name does exist
|
||||||
|
assertTrue(repository.getNameRepository().nameExists(name2));
|
||||||
|
|
||||||
|
// check that there are 2 names for one account
|
||||||
|
List<NameData> namesByOwner = repository.getNameRepository().getNamesByOwner(alice.getAddress(), 0, 0, false);
|
||||||
|
|
||||||
|
assertEquals(2, namesByOwner.size());
|
||||||
|
|
||||||
|
// check that the order is correct
|
||||||
|
assertEquals(name1, namesByOwner.get(0).getName());
|
||||||
|
|
||||||
|
String newestName = "newest-name";
|
||||||
|
String newestReducedName = "newest-name";
|
||||||
|
String newestData = "newest-data";
|
||||||
|
TransactionData newestTransactionData = new UpdateNameTransactionData(TestTransaction.generateBase(alice), name2, newestName, newestData);
|
||||||
|
TransactionUtils.signAndMint(repository, newestTransactionData, alice);
|
||||||
|
|
||||||
|
// Check previous name no longer exists
|
||||||
|
assertFalse(repository.getNameRepository().nameExists(name2));
|
||||||
|
|
||||||
|
// Check newest name exists
|
||||||
|
assertTrue(repository.getNameRepository().nameExists(newestName));
|
||||||
|
|
||||||
|
Optional<String> alicePrimaryName1 = alice.getPrimaryName();
|
||||||
|
|
||||||
|
assertTrue( alicePrimaryName1.isPresent() );
|
||||||
|
assertEquals( name1, alicePrimaryName1.get() );
|
||||||
|
|
||||||
|
// orphan and recheck
|
||||||
|
BlockUtils.orphanLastBlock(repository);
|
||||||
|
|
||||||
|
Optional<String> alicePrimaryName2 = alice.getPrimaryName();
|
||||||
|
|
||||||
|
assertTrue( alicePrimaryName2.isPresent() );
|
||||||
|
assertEquals( name1, alicePrimaryName2.get() );
|
||||||
|
|
||||||
|
// Check newest name no longer exists
|
||||||
|
assertFalse(repository.getNameRepository().nameExists(newestName));
|
||||||
|
assertNull(repository.getNameRepository().fromReducedName(newestReducedName));
|
||||||
|
|
||||||
|
// Check previous name exists again
|
||||||
|
assertTrue(repository.getNameRepository().nameExists(name2));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -3,8 +3,12 @@ package org.qortal.test.naming;
|
|||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.qortal.account.PrivateKeyAccount;
|
import org.qortal.account.PrivateKeyAccount;
|
||||||
|
import org.qortal.api.resource.TransactionsResource;
|
||||||
|
import org.qortal.block.BlockChain;
|
||||||
import org.qortal.data.naming.NameData;
|
import org.qortal.data.naming.NameData;
|
||||||
|
import org.qortal.data.transaction.BuyNameTransactionData;
|
||||||
import org.qortal.data.transaction.RegisterNameTransactionData;
|
import org.qortal.data.transaction.RegisterNameTransactionData;
|
||||||
|
import org.qortal.data.transaction.SellNameTransactionData;
|
||||||
import org.qortal.data.transaction.TransactionData;
|
import org.qortal.data.transaction.TransactionData;
|
||||||
import org.qortal.data.transaction.UpdateNameTransactionData;
|
import org.qortal.data.transaction.UpdateNameTransactionData;
|
||||||
import org.qortal.repository.DataException;
|
import org.qortal.repository.DataException;
|
||||||
@@ -15,6 +19,9 @@ import org.qortal.test.common.Common;
|
|||||||
import org.qortal.test.common.TransactionUtils;
|
import org.qortal.test.common.TransactionUtils;
|
||||||
import org.qortal.test.common.transaction.TestTransaction;
|
import org.qortal.test.common.transaction.TestTransaction;
|
||||||
import org.qortal.transaction.RegisterNameTransaction;
|
import org.qortal.transaction.RegisterNameTransaction;
|
||||||
|
import org.qortal.transaction.Transaction;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
@@ -395,6 +402,13 @@ public class UpdateTests extends Common {
|
|||||||
assertTrue(repository.getNameRepository().nameExists(initialName));
|
assertTrue(repository.getNameRepository().nameExists(initialName));
|
||||||
assertNotNull(repository.getNameRepository().fromReducedName(initialReducedName));
|
assertNotNull(repository.getNameRepository().fromReducedName(initialReducedName));
|
||||||
|
|
||||||
|
// move passed primary initiation
|
||||||
|
BlockUtils.mintBlocks(repository, BlockChain.getInstance().getMultipleNamesPerAccountHeight());
|
||||||
|
|
||||||
|
// check primary name
|
||||||
|
assertTrue(alice.getPrimaryName().isPresent());
|
||||||
|
assertEquals(initialName, alice.getPrimaryName().get());
|
||||||
|
|
||||||
// Update data
|
// Update data
|
||||||
String middleName = "middle-name";
|
String middleName = "middle-name";
|
||||||
String middleReducedName = "midd1e-name";
|
String middleReducedName = "midd1e-name";
|
||||||
@@ -402,6 +416,11 @@ public class UpdateTests extends Common {
|
|||||||
transactionData = new UpdateNameTransactionData(TestTransaction.generateBase(alice), initialName, middleName, middleData);
|
transactionData = new UpdateNameTransactionData(TestTransaction.generateBase(alice), initialName, middleName, middleData);
|
||||||
TransactionUtils.signAndMint(repository, transactionData, alice);
|
TransactionUtils.signAndMint(repository, transactionData, alice);
|
||||||
|
|
||||||
|
// check primary name
|
||||||
|
Optional<String> alicePrimaryName1 = alice.getPrimaryName();
|
||||||
|
assertTrue(alicePrimaryName1.isPresent());
|
||||||
|
assertEquals(middleName, alicePrimaryName1.get());
|
||||||
|
|
||||||
// Check data is correct
|
// Check data is correct
|
||||||
assertEquals(middleData, repository.getNameRepository().fromName(middleName).getData());
|
assertEquals(middleData, repository.getNameRepository().fromName(middleName).getData());
|
||||||
|
|
||||||
@@ -414,6 +433,11 @@ public class UpdateTests extends Common {
|
|||||||
// Check data is correct
|
// Check data is correct
|
||||||
assertEquals(newestData, repository.getNameRepository().fromName(newestName).getData());
|
assertEquals(newestData, repository.getNameRepository().fromName(newestName).getData());
|
||||||
|
|
||||||
|
// check primary name
|
||||||
|
Optional<String> alicePrimaryName2 = alice.getPrimaryName();
|
||||||
|
assertTrue(alicePrimaryName2.isPresent());
|
||||||
|
assertEquals(newestName, alicePrimaryName2.get());
|
||||||
|
|
||||||
// Check initial name no longer exists
|
// Check initial name no longer exists
|
||||||
assertFalse(repository.getNameRepository().nameExists(initialName));
|
assertFalse(repository.getNameRepository().nameExists(initialName));
|
||||||
assertNull(repository.getNameRepository().fromReducedName(initialReducedName));
|
assertNull(repository.getNameRepository().fromReducedName(initialReducedName));
|
||||||
@@ -516,4 +540,101 @@ public class UpdateTests extends Common {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testUpdatePrimaryName() throws DataException {
|
||||||
|
try (final Repository repository = RepositoryManager.getRepository()) {
|
||||||
|
// mint passed the feature trigger block
|
||||||
|
BlockUtils.mintBlocks(repository, BlockChain.getInstance().getMultipleNamesPerAccountHeight());
|
||||||
|
|
||||||
|
PrivateKeyAccount alice = Common.getTestAccount(repository, "alice");
|
||||||
|
PrivateKeyAccount bob = Common.getTestAccount(repository, "bob");
|
||||||
|
|
||||||
|
// register name 1
|
||||||
|
String initialName = "initial-name";
|
||||||
|
RegisterNameTransactionData registerNameTransactionData1 = new RegisterNameTransactionData(TestTransaction.generateBase(alice), initialName, "{}");
|
||||||
|
registerNameTransactionData1.setFee(new RegisterNameTransaction(null, null).getUnitFee(registerNameTransactionData1.getTimestamp()));
|
||||||
|
TransactionUtils.signAndMint(repository, registerNameTransactionData1, alice);
|
||||||
|
|
||||||
|
// assert name 1 registration, assert primary name
|
||||||
|
assertTrue(repository.getNameRepository().nameExists(initialName));
|
||||||
|
|
||||||
|
Optional<String> primaryNameOptional = alice.getPrimaryName();
|
||||||
|
assertTrue(primaryNameOptional.isPresent());
|
||||||
|
assertEquals(initialName, primaryNameOptional.get());
|
||||||
|
|
||||||
|
// register name 2
|
||||||
|
String secondName = "second-name";
|
||||||
|
RegisterNameTransactionData registerNameTransactionData2 = new RegisterNameTransactionData(TestTransaction.generateBase(alice), secondName, "{}");
|
||||||
|
registerNameTransactionData2.setFee(new RegisterNameTransaction(null, null).getUnitFee(registerNameTransactionData2.getTimestamp()));
|
||||||
|
TransactionUtils.signAndMint(repository, registerNameTransactionData2, alice);
|
||||||
|
|
||||||
|
// assert name 2 registration, assert primary has not changed
|
||||||
|
assertTrue(repository.getNameRepository().nameExists(secondName));
|
||||||
|
|
||||||
|
// the name alice is trying to update to
|
||||||
|
String newName = "updated-name";
|
||||||
|
|
||||||
|
// update name, assert invalid
|
||||||
|
updateName(repository, initialName, newName, Transaction.ValidationResult.NOT_SUPPORTED, alice);
|
||||||
|
|
||||||
|
// check primary name did not update
|
||||||
|
// check primary name update
|
||||||
|
Optional<String> primaryNameNotUpdateOptional = alice.getPrimaryName();
|
||||||
|
assertTrue(primaryNameNotUpdateOptional.isPresent());
|
||||||
|
assertEquals(initialName, primaryNameNotUpdateOptional.get());
|
||||||
|
|
||||||
|
// sell name 2, assert valid
|
||||||
|
Long amount = 1000000L;
|
||||||
|
SellNameTransactionData transactionData = new SellNameTransactionData(TestTransaction.generateBase(alice), secondName, amount);
|
||||||
|
TransactionUtils.signAndMint(repository, transactionData, alice);
|
||||||
|
|
||||||
|
// Check name is for sale
|
||||||
|
NameData nameData = repository.getNameRepository().fromName(secondName);
|
||||||
|
assertTrue(nameData.isForSale());
|
||||||
|
assertEquals("price incorrect", amount, nameData.getSalePrice());
|
||||||
|
|
||||||
|
// bob buys name 2, assert
|
||||||
|
BuyNameTransactionData bobBuysName2Data = new BuyNameTransactionData(TestTransaction.generateBase(bob), secondName, amount, alice.getAddress());
|
||||||
|
TransactionUtils.signAndMint(repository, bobBuysName2Data, bob);
|
||||||
|
|
||||||
|
// update name, assert valid, assert primary name change
|
||||||
|
updateName(repository, initialName, newName, Transaction.ValidationResult.OK, alice);
|
||||||
|
|
||||||
|
// check primary name update
|
||||||
|
Optional<String> primaryNameUpdateOptional = alice.getPrimaryName();
|
||||||
|
assertTrue(primaryNameUpdateOptional.isPresent());
|
||||||
|
assertEquals(newName, primaryNameUpdateOptional.get());
|
||||||
|
|
||||||
|
assertEquals(alice.getPrimaryName(), alice.determinePrimaryName(TransactionsResource.ConfirmationStatus.CONFIRMED));
|
||||||
|
assertEquals(bob.getPrimaryName(), bob.determinePrimaryName(TransactionsResource.ConfirmationStatus.CONFIRMED));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update Name
|
||||||
|
*
|
||||||
|
* @param repository
|
||||||
|
* @param initialName the name before the update
|
||||||
|
* @param newName the name after the update
|
||||||
|
* @param expectedValidationResult the validation result expected from the update
|
||||||
|
* @param account the account for the update
|
||||||
|
*
|
||||||
|
* @throws DataException
|
||||||
|
*/
|
||||||
|
private static void updateName(Repository repository, String initialName, String newName, Transaction.ValidationResult expectedValidationResult, PrivateKeyAccount account) throws DataException {
|
||||||
|
TransactionData data = new UpdateNameTransactionData(TestTransaction.generateBase(account), initialName, newName, "{}");
|
||||||
|
Transaction.ValidationResult result = TransactionUtils.signAndImport(repository,data, account);
|
||||||
|
|
||||||
|
assertEquals("Transaction invalid", expectedValidationResult, result);
|
||||||
|
|
||||||
|
BlockUtils.mintBlock(repository);
|
||||||
|
|
||||||
|
if( Transaction.ValidationResult.OK.equals(expectedValidationResult) ) {
|
||||||
|
assertTrue(repository.getNameRepository().nameExists(newName));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// the new name should not exist, because the update was invalid
|
||||||
|
assertFalse(repository.getNameRepository().nameExists(newName));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user