diff --git a/src/main/java/org/qortal/controller/Controller.java b/src/main/java/org/qortal/controller/Controller.java index e1e90486..2cab24ec 100644 --- a/src/main/java/org/qortal/controller/Controller.java +++ b/src/main/java/org/qortal/controller/Controller.java @@ -1278,13 +1278,6 @@ public class Controller extends Thread { TransactionImporter.getInstance().onNetworkTransactionSignaturesMessage(peer, message); break; - case GET_ONLINE_ACCOUNTS: - case ONLINE_ACCOUNTS: - case GET_ONLINE_ACCOUNTS_V2: - case ONLINE_ACCOUNTS_V2: - // No longer supported - to be eventually removed - break; - case GET_ONLINE_ACCOUNTS_V3: OnlineAccountsManager.getInstance().onNetworkGetOnlineAccountsV3Message(peer, message); break; diff --git a/src/main/java/org/qortal/network/message/GetOnlineAccountsMessage.java b/src/main/java/org/qortal/network/message/GetOnlineAccountsMessage.java deleted file mode 100644 index ae98cf40..00000000 --- a/src/main/java/org/qortal/network/message/GetOnlineAccountsMessage.java +++ /dev/null @@ -1,69 +0,0 @@ -package org.qortal.network.message; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.List; -import java.util.stream.Collectors; - -import org.qortal.data.network.OnlineAccountData; -import org.qortal.transform.Transformer; - -import com.google.common.primitives.Ints; -import com.google.common.primitives.Longs; - -public class GetOnlineAccountsMessage extends Message { - private static final int MAX_ACCOUNT_COUNT = 5000; - - private List onlineAccounts; - - public GetOnlineAccountsMessage(List onlineAccounts) { - super(MessageType.GET_ONLINE_ACCOUNTS); - - ByteArrayOutputStream bytes = new ByteArrayOutputStream(); - - try { - bytes.write(Ints.toByteArray(onlineAccounts.size())); - - for (OnlineAccountData onlineAccountData : onlineAccounts) { - bytes.write(Longs.toByteArray(onlineAccountData.getTimestamp())); - - bytes.write(onlineAccountData.getPublicKey()); - } - } catch (IOException e) { - throw new AssertionError("IOException shouldn't occur with ByteArrayOutputStream"); - } - - this.dataBytes = bytes.toByteArray(); - this.checksumBytes = Message.generateChecksum(this.dataBytes); - } - - private GetOnlineAccountsMessage(int id, List onlineAccounts) { - super(id, MessageType.GET_ONLINE_ACCOUNTS); - - this.onlineAccounts = onlineAccounts.stream().limit(MAX_ACCOUNT_COUNT).collect(Collectors.toList()); - } - - public List getOnlineAccounts() { - return this.onlineAccounts; - } - - public static Message fromByteBuffer(int id, ByteBuffer bytes) { - final int accountCount = bytes.getInt(); - - List onlineAccounts = new ArrayList<>(accountCount); - - for (int i = 0; i < Math.min(MAX_ACCOUNT_COUNT, accountCount); ++i) { - long timestamp = bytes.getLong(); - - byte[] publicKey = new byte[Transformer.PUBLIC_KEY_LENGTH]; - bytes.get(publicKey); - - onlineAccounts.add(new OnlineAccountData(timestamp, null, publicKey)); - } - - return new GetOnlineAccountsMessage(id, onlineAccounts); - } - -} diff --git a/src/main/java/org/qortal/network/message/GetOnlineAccountsV2Message.java b/src/main/java/org/qortal/network/message/GetOnlineAccountsV2Message.java deleted file mode 100644 index fe6b5d72..00000000 --- a/src/main/java/org/qortal/network/message/GetOnlineAccountsV2Message.java +++ /dev/null @@ -1,109 +0,0 @@ -package org.qortal.network.message; - -import com.google.common.primitives.Ints; -import com.google.common.primitives.Longs; -import org.qortal.data.network.OnlineAccountData; -import org.qortal.transform.Transformer; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * For requesting online accounts info from remote peer, given our list of online accounts. - * - * Different format to V1: - * V1 is: number of entries, then timestamp + pubkey for each entry - * V2 is: groups of: number of entries, timestamp, then pubkey for each entry - * - * Also V2 only builds online accounts message once! - */ -public class GetOnlineAccountsV2Message extends Message { - - private List onlineAccounts; - - public GetOnlineAccountsV2Message(List onlineAccounts) { - super(MessageType.GET_ONLINE_ACCOUNTS_V2); - - // If we don't have ANY online accounts then it's an easier construction... - if (onlineAccounts.isEmpty()) { - // Always supply a number of accounts - this.dataBytes = Ints.toByteArray(0); - this.checksumBytes = Message.generateChecksum(this.dataBytes); - return; - } - - // How many of each timestamp - Map countByTimestamp = new HashMap<>(); - - for (OnlineAccountData onlineAccountData : onlineAccounts) { - Long timestamp = onlineAccountData.getTimestamp(); - countByTimestamp.compute(timestamp, (k, v) -> v == null ? 1 : ++v); - } - - // We should know exactly how many bytes to allocate now - int byteSize = countByTimestamp.size() * (Transformer.INT_LENGTH + Transformer.TIMESTAMP_LENGTH) - + onlineAccounts.size() * Transformer.PUBLIC_KEY_LENGTH; - - ByteArrayOutputStream bytes = new ByteArrayOutputStream(byteSize); - - try { - for (long timestamp : countByTimestamp.keySet()) { - bytes.write(Ints.toByteArray(countByTimestamp.get(timestamp))); - - bytes.write(Longs.toByteArray(timestamp)); - - for (OnlineAccountData onlineAccountData : onlineAccounts) { - if (onlineAccountData.getTimestamp() == timestamp) - bytes.write(onlineAccountData.getPublicKey()); - } - } - } catch (IOException e) { - throw new AssertionError("IOException shouldn't occur with ByteArrayOutputStream"); - } - - this.dataBytes = bytes.toByteArray(); - this.checksumBytes = Message.generateChecksum(this.dataBytes); - } - - private GetOnlineAccountsV2Message(int id, List onlineAccounts) { - super(id, MessageType.GET_ONLINE_ACCOUNTS_V2); - - this.onlineAccounts = onlineAccounts; - } - - public List getOnlineAccounts() { - return this.onlineAccounts; - } - - public static Message fromByteBuffer(int id, ByteBuffer bytes) { - int accountCount = bytes.getInt(); - - List onlineAccounts = new ArrayList<>(accountCount); - - while (accountCount > 0) { - long timestamp = bytes.getLong(); - - for (int i = 0; i < accountCount; ++i) { - byte[] publicKey = new byte[Transformer.PUBLIC_KEY_LENGTH]; - bytes.get(publicKey); - - onlineAccounts.add(new OnlineAccountData(timestamp, null, publicKey)); - } - - if (bytes.hasRemaining()) { - accountCount = bytes.getInt(); - } else { - // we've finished - accountCount = 0; - } - } - - return new GetOnlineAccountsV2Message(id, onlineAccounts); - } - -} diff --git a/src/main/java/org/qortal/network/message/MessageType.java b/src/main/java/org/qortal/network/message/MessageType.java index 4dd4a3c8..6b420e2d 100644 --- a/src/main/java/org/qortal/network/message/MessageType.java +++ b/src/main/java/org/qortal/network/message/MessageType.java @@ -43,11 +43,7 @@ public enum MessageType { BLOCK_SUMMARIES(70, BlockSummariesMessage::fromByteBuffer), GET_BLOCK_SUMMARIES(71, GetBlockSummariesMessage::fromByteBuffer), BLOCK_SUMMARIES_V2(72, BlockSummariesV2Message::fromByteBuffer), - - ONLINE_ACCOUNTS(80, OnlineAccountsMessage::fromByteBuffer), - GET_ONLINE_ACCOUNTS(81, GetOnlineAccountsMessage::fromByteBuffer), - ONLINE_ACCOUNTS_V2(82, OnlineAccountsV2Message::fromByteBuffer), - GET_ONLINE_ACCOUNTS_V2(83, GetOnlineAccountsV2Message::fromByteBuffer), + ONLINE_ACCOUNTS_V3(84, OnlineAccountsV3Message::fromByteBuffer), GET_ONLINE_ACCOUNTS_V3(85, GetOnlineAccountsV3Message::fromByteBuffer), diff --git a/src/main/java/org/qortal/network/message/OnlineAccountsMessage.java b/src/main/java/org/qortal/network/message/OnlineAccountsMessage.java deleted file mode 100644 index e7e4c32c..00000000 --- a/src/main/java/org/qortal/network/message/OnlineAccountsMessage.java +++ /dev/null @@ -1,75 +0,0 @@ -package org.qortal.network.message; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.List; -import java.util.stream.Collectors; - -import org.qortal.data.network.OnlineAccountData; -import org.qortal.transform.Transformer; - -import com.google.common.primitives.Ints; -import com.google.common.primitives.Longs; - -public class OnlineAccountsMessage extends Message { - private static final int MAX_ACCOUNT_COUNT = 5000; - - private List onlineAccounts; - - public OnlineAccountsMessage(List onlineAccounts) { - super(MessageType.ONLINE_ACCOUNTS); - - ByteArrayOutputStream bytes = new ByteArrayOutputStream(); - - try { - bytes.write(Ints.toByteArray(onlineAccounts.size())); - - for (OnlineAccountData onlineAccountData : onlineAccounts) { - bytes.write(Longs.toByteArray(onlineAccountData.getTimestamp())); - - bytes.write(onlineAccountData.getSignature()); - - bytes.write(onlineAccountData.getPublicKey()); - } - } catch (IOException e) { - throw new AssertionError("IOException shouldn't occur with ByteArrayOutputStream"); - } - - this.dataBytes = bytes.toByteArray(); - this.checksumBytes = Message.generateChecksum(this.dataBytes); - } - - private OnlineAccountsMessage(int id, List onlineAccounts) { - super(id, MessageType.ONLINE_ACCOUNTS); - - this.onlineAccounts = onlineAccounts.stream().limit(MAX_ACCOUNT_COUNT).collect(Collectors.toList()); - } - - public List getOnlineAccounts() { - return this.onlineAccounts; - } - - public static Message fromByteBuffer(int id, ByteBuffer bytes) { - final int accountCount = bytes.getInt(); - - List onlineAccounts = new ArrayList<>(accountCount); - - for (int i = 0; i < Math.min(MAX_ACCOUNT_COUNT, accountCount); ++i) { - long timestamp = bytes.getLong(); - - byte[] signature = new byte[Transformer.SIGNATURE_LENGTH]; - bytes.get(signature); - - byte[] publicKey = new byte[Transformer.PUBLIC_KEY_LENGTH]; - bytes.get(publicKey); - - OnlineAccountData onlineAccountData = new OnlineAccountData(timestamp, signature, publicKey); - onlineAccounts.add(onlineAccountData); - } - - return new OnlineAccountsMessage(id, onlineAccounts); - } - -} diff --git a/src/main/java/org/qortal/network/message/OnlineAccountsV2Message.java b/src/main/java/org/qortal/network/message/OnlineAccountsV2Message.java deleted file mode 100644 index 6803e3bf..00000000 --- a/src/main/java/org/qortal/network/message/OnlineAccountsV2Message.java +++ /dev/null @@ -1,113 +0,0 @@ -package org.qortal.network.message; - -import com.google.common.primitives.Ints; -import com.google.common.primitives.Longs; -import org.qortal.data.network.OnlineAccountData; -import org.qortal.transform.Transformer; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * For sending online accounts info to remote peer. - * - * Different format to V1: - * V1 is: number of entries, then timestamp + sig + pubkey for each entry - * V2 is: groups of: number of entries, timestamp, then sig + pubkey for each entry - * - * Also V2 only builds online accounts message once! - */ -public class OnlineAccountsV2Message extends Message { - - private List onlineAccounts; - - public OnlineAccountsV2Message(List onlineAccounts) { - super(MessageType.ONLINE_ACCOUNTS_V2); - - // Shortcut in case we have no online accounts - if (onlineAccounts.isEmpty()) { - this.dataBytes = Ints.toByteArray(0); - this.checksumBytes = Message.generateChecksum(this.dataBytes); - return; - } - - // How many of each timestamp - Map countByTimestamp = new HashMap<>(); - - for (OnlineAccountData onlineAccountData : onlineAccounts) { - Long timestamp = onlineAccountData.getTimestamp(); - countByTimestamp.compute(timestamp, (k, v) -> v == null ? 1 : ++v); - } - - // We should know exactly how many bytes to allocate now - int byteSize = countByTimestamp.size() * (Transformer.INT_LENGTH + Transformer.TIMESTAMP_LENGTH) - + onlineAccounts.size() * (Transformer.SIGNATURE_LENGTH + Transformer.PUBLIC_KEY_LENGTH); - - ByteArrayOutputStream bytes = new ByteArrayOutputStream(byteSize); - - try { - for (long timestamp : countByTimestamp.keySet()) { - bytes.write(Ints.toByteArray(countByTimestamp.get(timestamp))); - - bytes.write(Longs.toByteArray(timestamp)); - - for (OnlineAccountData onlineAccountData : onlineAccounts) { - if (onlineAccountData.getTimestamp() == timestamp) { - bytes.write(onlineAccountData.getSignature()); - bytes.write(onlineAccountData.getPublicKey()); - } - } - } - } catch (IOException e) { - throw new AssertionError("IOException shouldn't occur with ByteArrayOutputStream"); - } - - this.dataBytes = bytes.toByteArray(); - this.checksumBytes = Message.generateChecksum(this.dataBytes); - } - - private OnlineAccountsV2Message(int id, List onlineAccounts) { - super(id, MessageType.ONLINE_ACCOUNTS_V2); - - this.onlineAccounts = onlineAccounts; - } - - public List getOnlineAccounts() { - return this.onlineAccounts; - } - - public static Message fromByteBuffer(int id, ByteBuffer bytes) throws MessageException { - int accountCount = bytes.getInt(); - - List onlineAccounts = new ArrayList<>(accountCount); - - while (accountCount > 0) { - long timestamp = bytes.getLong(); - - for (int i = 0; i < accountCount; ++i) { - byte[] signature = new byte[Transformer.SIGNATURE_LENGTH]; - bytes.get(signature); - - byte[] publicKey = new byte[Transformer.PUBLIC_KEY_LENGTH]; - bytes.get(publicKey); - - onlineAccounts.add(new OnlineAccountData(timestamp, signature, publicKey)); - } - - if (bytes.hasRemaining()) { - accountCount = bytes.getInt(); - } else { - // we've finished - accountCount = 0; - } - } - - return new OnlineAccountsV2Message(id, onlineAccounts); - } - -} diff --git a/src/test/java/org/qortal/test/network/OnlineAccountsTests.java b/src/test/java/org/qortal/test/network/OnlineAccountsTests.java index c9e646f1..c8220d66 100644 --- a/src/test/java/org/qortal/test/network/OnlineAccountsTests.java +++ b/src/test/java/org/qortal/test/network/OnlineAccountsTests.java @@ -51,89 +51,6 @@ public class OnlineAccountsTests extends Common { } - @Test - public void testGetOnlineAccountsV2() throws MessageException { - List onlineAccountsOut = generateOnlineAccounts(false); - - Message messageOut = new GetOnlineAccountsV2Message(onlineAccountsOut); - - byte[] messageBytes = messageOut.toBytes(); - ByteBuffer byteBuffer = ByteBuffer.wrap(messageBytes); - - GetOnlineAccountsV2Message messageIn = (GetOnlineAccountsV2Message) Message.fromByteBuffer(byteBuffer); - - List onlineAccountsIn = messageIn.getOnlineAccounts(); - - assertEquals("size mismatch", onlineAccountsOut.size(), onlineAccountsIn.size()); - assertTrue("accounts mismatch", onlineAccountsIn.containsAll(onlineAccountsOut)); - - Message oldMessageOut = new GetOnlineAccountsMessage(onlineAccountsOut); - byte[] oldMessageBytes = oldMessageOut.toBytes(); - - long numTimestamps = onlineAccountsOut.stream().mapToLong(OnlineAccountData::getTimestamp).sorted().distinct().count(); - - System.out.println(String.format("For %d accounts split across %d timestamp%s: old size %d vs new size %d", - onlineAccountsOut.size(), - numTimestamps, - numTimestamps != 1 ? "s" : "", - oldMessageBytes.length, - messageBytes.length)); - } - - @Test - public void testOnlineAccountsV2() throws MessageException { - List onlineAccountsOut = generateOnlineAccounts(true); - - Message messageOut = new OnlineAccountsV2Message(onlineAccountsOut); - - byte[] messageBytes = messageOut.toBytes(); - ByteBuffer byteBuffer = ByteBuffer.wrap(messageBytes); - - OnlineAccountsV2Message messageIn = (OnlineAccountsV2Message) Message.fromByteBuffer(byteBuffer); - - List onlineAccountsIn = messageIn.getOnlineAccounts(); - - assertEquals("size mismatch", onlineAccountsOut.size(), onlineAccountsIn.size()); - assertTrue("accounts mismatch", onlineAccountsIn.containsAll(onlineAccountsOut)); - - Message oldMessageOut = new OnlineAccountsMessage(onlineAccountsOut); - byte[] oldMessageBytes = oldMessageOut.toBytes(); - - long numTimestamps = onlineAccountsOut.stream().mapToLong(OnlineAccountData::getTimestamp).sorted().distinct().count(); - - System.out.println(String.format("For %d accounts split across %d timestamp%s: old size %d vs new size %d", - onlineAccountsOut.size(), - numTimestamps, - numTimestamps != 1 ? "s" : "", - oldMessageBytes.length, - messageBytes.length)); - } - - private List generateOnlineAccounts(boolean withSignatures) { - List onlineAccounts = new ArrayList<>(); - - int numTimestamps = RANDOM.nextInt(2) + 1; // 1 or 2 - - for (int t = 0; t < numTimestamps; ++t) { - int numAccounts = RANDOM.nextInt(3000); - - for (int a = 0; a < numAccounts; ++a) { - byte[] sig = null; - if (withSignatures) { - sig = new byte[Transformer.SIGNATURE_LENGTH]; - RANDOM.nextBytes(sig); - } - - byte[] pubkey = new byte[Transformer.PUBLIC_KEY_LENGTH]; - RANDOM.nextBytes(pubkey); - - onlineAccounts.add(new OnlineAccountData(t << 32, sig, pubkey)); - } - } - - return onlineAccounts; - } - @Test public void testOnlineAccountsModulusV1() throws IllegalAccessException, DataException { try (final Repository repository = RepositoryManager.getRepository()) { diff --git a/src/test/java/org/qortal/test/network/OnlineAccountsV3Tests.java b/src/test/java/org/qortal/test/network/OnlineAccountsV3Tests.java index 6136c1e1..cc2a54ff 100644 --- a/src/test/java/org/qortal/test/network/OnlineAccountsV3Tests.java +++ b/src/test/java/org/qortal/test/network/OnlineAccountsV3Tests.java @@ -26,41 +26,6 @@ public class OnlineAccountsV3Tests { Security.insertProviderAt(new BouncyCastleJsseProvider(), 1); } - @Ignore("For informational use") - @Test - public void compareV2ToV3() throws MessageException { - List onlineAccounts = generateOnlineAccounts(false); - - // How many of each timestamp and leading byte (of public key) - Map> hashesByTimestampThenByte = convertToHashMaps(onlineAccounts); - - byte[] v3DataBytes = new GetOnlineAccountsV3Message(hashesByTimestampThenByte).toBytes(); - int v3ByteSize = v3DataBytes.length; - - byte[] v2DataBytes = new GetOnlineAccountsV2Message(onlineAccounts).toBytes(); - int v2ByteSize = v2DataBytes.length; - - int numTimestamps = hashesByTimestampThenByte.size(); - System.out.printf("For %d accounts split across %d timestamp%s: V2 size %d vs V3 size %d%n", - onlineAccounts.size(), - numTimestamps, - numTimestamps != 1 ? "s" : "", - v2ByteSize, - v3ByteSize - ); - - for (var outerMapEntry : hashesByTimestampThenByte.entrySet()) { - long timestamp = outerMapEntry.getKey(); - - var innerMap = outerMapEntry.getValue(); - - System.out.printf("For timestamp %d: %d / 256 slots used.%n", - timestamp, - innerMap.size() - ); - } - } - private Map> convertToHashMaps(List onlineAccounts) { // How many of each timestamp and leading byte (of public key) Map> hashesByTimestampThenByte = new HashMap<>();