Browse Source

Added GET_NAME message to allow lookups from name to owner (or any other name data).

lite-node
CalDescent 3 years ago
parent
commit
59119ebc3b
  1. 12
      src/main/java/org/qortal/api/resource/NamesResource.java
  2. 48
      src/main/java/org/qortal/controller/Controller.java
  3. 19
      src/main/java/org/qortal/controller/LiteNode.java
  4. 55
      src/main/java/org/qortal/network/message/GetNameMessage.java
  5. 3
      src/main/java/org/qortal/network/message/Message.java

12
src/main/java/org/qortal/api/resource/NamesResource.java

@ -134,10 +134,18 @@ public class NamesResource {
@ApiErrors({ApiError.NAME_UNKNOWN, ApiError.REPOSITORY_ISSUE}) @ApiErrors({ApiError.NAME_UNKNOWN, ApiError.REPOSITORY_ISSUE})
public NameData getName(@PathParam("name") String name) { public NameData getName(@PathParam("name") String name) {
try (final Repository repository = RepositoryManager.getRepository()) { try (final Repository repository = RepositoryManager.getRepository()) {
NameData nameData = repository.getNameRepository().fromName(name); NameData nameData;
if (nameData == null) if (Settings.getInstance().isLite()) {
nameData = LiteNode.getInstance().fetchNameData(name);
}
else {
nameData = repository.getNameRepository().fromName(name);
}
if (nameData == null) {
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.NAME_UNKNOWN); throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.NAME_UNKNOWN);
}
return nameData; return nameData;
} catch (ApiException e) { } catch (ApiException e) {

48
src/main/java/org/qortal/controller/Controller.java

@ -209,6 +209,15 @@ public class Controller extends Thread {
} }
public GetAccountNamesMessageStats getAccountNamesMessageStats = new GetAccountNamesMessageStats(); public GetAccountNamesMessageStats getAccountNamesMessageStats = new GetAccountNamesMessageStats();
public static class GetNameMessageStats {
public AtomicLong requests = new AtomicLong();
public AtomicLong unknownAccounts = new AtomicLong();
public GetNameMessageStats() {
}
}
public GetNameMessageStats getNameMessageStats = new GetNameMessageStats();
public AtomicLong latestBlocksCacheRefills = new AtomicLong(); public AtomicLong latestBlocksCacheRefills = new AtomicLong();
public StatsSnapshot() { public StatsSnapshot() {
@ -1275,6 +1284,10 @@ public class Controller extends Thread {
onNetworkGetAccountNamesMessage(peer, message); onNetworkGetAccountNamesMessage(peer, message);
break; break;
case GET_NAME:
onNetworkGetNameMessage(peer, message);
break;
default: default:
LOGGER.debug(() -> String.format("Unhandled %s message [ID %d] from peer %s", message.getType().name(), message.getId(), peer)); LOGGER.debug(() -> String.format("Unhandled %s message [ID %d] from peer %s", message.getType().name(), message.getId(), peer));
break; break;
@ -1632,6 +1645,41 @@ public class Controller extends Thread {
} }
} }
private void onNetworkGetNameMessage(Peer peer, Message message) {
GetNameMessage getNameMessage = (GetNameMessage) message;
String name = getNameMessage.getName();
this.stats.getNameMessageStats.requests.incrementAndGet();
try (final Repository repository = RepositoryManager.getRepository()) {
NameData nameData = repository.getNameRepository().fromName(name);
if (nameData == null) {
// We don't have this account
this.stats.getNameMessageStats.unknownAccounts.getAndIncrement();
// Send valid, yet unexpected message type in response, so peer doesn't have to wait for timeout
LOGGER.debug(() -> String.format("Sending 'name unknown' response to peer %s for GET_NAME request for unknown name %s", peer, name));
// We'll send empty block summaries message as it's very short
Message nameUnknownMessage = new BlockSummariesMessage(Collections.emptyList());
nameUnknownMessage.setId(message.getId());
if (!peer.sendMessage(nameUnknownMessage))
peer.disconnect("failed to send name-unknown response");
return;
}
NamesMessage namesMessage = new NamesMessage(Arrays.asList(nameData));
namesMessage.setId(message.getId());
if (!peer.sendMessage(namesMessage)) {
peer.disconnect("failed to send name data");
}
} catch (DataException e) {
LOGGER.error(String.format("Repository issue while send name %s to peer %s", name, peer), e);
}
}
// Utilities // Utilities

19
src/main/java/org/qortal/controller/LiteNode.java

@ -80,6 +80,25 @@ public class LiteNode {
return namesMessage.getNameDataList(); return namesMessage.getNameDataList();
} }
/**
* Fetch info about a registered name
* @param name - the name to query
* @return a NameData object, or null if not retrieved
*/
public NameData fetchNameData(String name) {
GetNameMessage getNameMessage = new GetNameMessage(name);
NamesMessage namesMessage = (NamesMessage) this.sendMessage(getNameMessage, NAMES);
if (namesMessage == null) {
return null;
}
List<NameData> nameDataList = namesMessage.getNameDataList();
if (nameDataList == null || nameDataList.size() != 1) {
return null;
}
// We are only expecting a single item in the list
return nameDataList.get(0);
}
private Message sendMessage(Message message, MessageType expectedResponseMessageType) { private Message sendMessage(Message message, MessageType expectedResponseMessageType) {
// This asks a random peer for the data // This asks a random peer for the data

55
src/main/java/org/qortal/network/message/GetNameMessage.java

@ -0,0 +1,55 @@
package org.qortal.network.message;
import org.qortal.naming.Name;
import org.qortal.transform.TransformationException;
import org.qortal.transform.Transformer;
import org.qortal.utils.Serialization;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
public class GetNameMessage extends Message {
private String name;
public GetNameMessage(String address) {
this(-1, address);
}
private GetNameMessage(int id, String name) {
super(id, MessageType.GET_NAME);
this.name = name;
}
public String getName() {
return this.name;
}
public static Message fromByteBuffer(int id, ByteBuffer bytes) throws UnsupportedEncodingException {
try {
String name = Serialization.deserializeSizedStringV2(bytes, Name.MAX_NAME_SIZE);
return new GetNameMessage(id, name);
} catch (TransformationException e) {
return null;
}
}
@Override
protected byte[] toData() {
try {
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
Serialization.serializeSizedStringV2(bytes, this.name);
return bytes.toByteArray();
} catch (IOException e) {
return null;
}
}
}

3
src/main/java/org/qortal/network/message/Message.java

@ -109,7 +109,8 @@ public abstract class Message {
GET_ACCOUNT_BALANCE(171), GET_ACCOUNT_BALANCE(171),
NAMES(180), NAMES(180),
GET_ACCOUNT_NAMES(181); GET_ACCOUNT_NAMES(181),
GET_NAME(182);
public final int value; public final int value;
public final Method fromByteBufferMethod; public final Method fromByteBufferMethod;

Loading…
Cancel
Save