Skip to content

Commit

Permalink
refactor: return AddressBook from AddressBookRoster (#11511)
Browse files Browse the repository at this point in the history
Signed-off-by: Edward Wertz <edward@swirldslabs.com>
  • Loading branch information
edward-swirldslabs authored and imalygin committed Feb 16, 2024
1 parent dd821d8 commit bf20bc0
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 69 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -49,25 +49,39 @@ private static final class ClassVersion {

private final Map<NodeId, RosterEntry> entries = new HashMap<>();
private List<NodeId> nodeOrder;
private AddressBook addressBook;

/**
* Constructs a new {@link AddressBookRoster} from the given {@link AddressBook} and {@link KeysAndCerts} map.
*
* @param addressBook the address book
* @param keysAndCertsMap the keys and certs map
*/
public AddressBookRoster(
@NonNull final AddressBook addressBook, @NonNull final Map<NodeId, KeysAndCerts> keysAndCertsMap) {
Objects.requireNonNull(addressBook);
Objects.requireNonNull(keysAndCertsMap);
public AddressBookRoster(@NonNull final AddressBook addressBook) {
this.addressBook = Objects.requireNonNull(addressBook);
setupRosterFromAddressBook();
}

/**
* Populates the AddressRosterEntry map from the AddressBook and determines the node order.
*/
private void setupRosterFromAddressBook() {
for (final Address address : addressBook) {
entries.put(address.getNodeId(), new AddressRosterEntry(address, keysAndCertsMap.get(address.getNodeId())));
entries.put(address.getNodeId(), new AddressRosterEntry(address));
}

nodeOrder = entries.keySet().stream().sorted().toList();
}

/**
* Returns the address book.
*
* @return the address book
*/
@NonNull
public AddressBook getAddressBook() {
return addressBook;
}

/**
* Empty constructor for deserialization.
*/
Expand All @@ -87,20 +101,13 @@ public int getVersion() {

@Override
public void serialize(@NonNull final SerializableDataOutputStream out) throws IOException {
out.writeInt(entries.size());
for (final RosterEntry entry : this) {
out.writeSerializable(entry, true);
}
out.writeSerializable(addressBook, false);
}

@Override
public void deserialize(@NonNull final SerializableDataInputStream in, final int version) throws IOException {
final int size = in.readInt();
for (int i = 0; i < size; i++) {
final RosterEntry entry = in.readSerializable();
entries.put(entry.getNodeId(), entry);
}
nodeOrder = entries.keySet().stream().sorted().toList();
addressBook = in.readSerializable(false, AddressBook::new);
setupRosterFromAddressBook();
}

@Override
Expand Down Expand Up @@ -147,12 +154,14 @@ public boolean equals(@Nullable final Object o) {
return false;
}
final AddressBookRoster that = (AddressBookRoster) o;
return Objects.equals(entries, that.entries);
return Objects.equals(addressBook, that.addressBook)
&& Objects.equals(entries, that.entries)
&& Objects.equals(nodeOrder, that.nodeOrder);
}

@Override
public int hashCode() {
return Objects.hash(entries);
return Objects.hash(addressBook);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,7 @@
import com.swirlds.platform.system.address.Address;
import edu.umd.cs.findbugs.annotations.NonNull;
import edu.umd.cs.findbugs.annotations.Nullable;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.security.cert.CertificateEncodingException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.Objects;

Expand All @@ -44,30 +40,32 @@ private static final class ClassVersion {
public static final int ORIGINAL = 1;
}

private static final int ENCODED_CERT_MAX_SIZE = 8192;

private Address address;
private X509Certificate sigCert;

/**
* Constructs a new {@link AddressRosterEntry} from the given {@link Address} and {@link KeysAndCerts}.
*
* @param address the address
* @param keysAndCerts the keys and certs containing the signing certificate
* @param address the address
*/
public AddressRosterEntry(@NonNull final Address address, @NonNull final KeysAndCerts keysAndCerts) {
Objects.requireNonNull(address);
Objects.requireNonNull(keysAndCerts);

this.address = address;
this.sigCert = keysAndCerts.sigCert();
public AddressRosterEntry(@NonNull final Address address) {
this.address = Objects.requireNonNull(address);
}

/**
* Empty constructor for deserialization.
*/
public AddressRosterEntry() {}

/**
* Returns the address.
*
* @return the address
*/
@NonNull
public Address getAddress() {
return address;
}

/**
* {@inheritDoc}
*/
Expand All @@ -87,23 +85,11 @@ public int getVersion() {
@Override
public void serialize(@NonNull final SerializableDataOutputStream out) throws IOException {
out.writeSerializable(address, false);
try {
out.writeByteArray(sigCert.getEncoded());
} catch (final CertificateEncodingException e) {
throw new IOException("Could not encode certificate", e);
}
}

@Override
public void deserialize(@NonNull final SerializableDataInputStream in, final int version) throws IOException {
address = in.readSerializable(false, Address::new);
final byte[] encodedCert = in.readByteArray(ENCODED_CERT_MAX_SIZE);
try {
sigCert = (X509Certificate)
CertificateFactory.getInstance("X.509").generateCertificate(new ByteArrayInputStream(encodedCert));
} catch (final CertificateException e) {
throw new IOException("Could not decode certificate", e);
}
}

@Override
Expand Down Expand Up @@ -131,7 +117,7 @@ public int getPort() {
@NonNull
@Override
public X509Certificate getSigningCertificate() {
return sigCert;
return Objects.requireNonNull(address.getSigCert());
}

@Override
Expand All @@ -143,20 +129,17 @@ public boolean equals(@Nullable final Object o) {
return false;
}
final AddressRosterEntry that = (AddressRosterEntry) o;
return Objects.equals(address, that.address) && Objects.equals(sigCert, that.sigCert);
return Objects.equals(address, that.address);
}

@Override
public int hashCode() {
return Objects.hash(address, sigCert);
return Objects.hash(address);
}

@Override
public String toString() {

return new ToStringBuilder(this)
.append("address", address)
.append("sigCert", sigCert)
.toString();
return new ToStringBuilder(this).append("address", address).toString();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,31 +24,27 @@
import com.swirlds.common.io.streams.SerializableDataInputStream;
import com.swirlds.common.io.streams.SerializableDataOutputStream;
import com.swirlds.common.platform.NodeId;
import com.swirlds.platform.crypto.KeysAndCerts;
import com.swirlds.platform.roster.Roster;
import com.swirlds.platform.roster.RosterEntry;
import com.swirlds.platform.system.address.Address;
import com.swirlds.platform.system.address.AddressBook;
import edu.umd.cs.findbugs.annotations.NonNull;
import com.swirlds.platform.test.fixtures.addressbook.RandomAddressBookGenerator;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Iterator;
import java.util.Map;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;
import org.junit.jupiter.api.Test;

public class AddressBookRosterTests {

@Test
@DisplayName("Serialize and deserialize AddressBook derived Roster")
@ParameterizedTest
@MethodSource({"com.swirlds.platform.crypto.CryptoArgsProvider#basicTestArgs"})
void serializeDeserializeTest(
@NonNull final AddressBook addressBook, @NonNull final Map<NodeId, KeysAndCerts> keysAndCerts)
throws IOException, ConstructableRegistryException {
void serializeDeserializeTest() throws IOException, ConstructableRegistryException {
final AddressBook addressBook =
new RandomAddressBookGenerator().setSize(100).build();
ConstructableRegistry.getInstance().registerConstructables("com.swirlds");
final Roster roster = new AddressBookRoster(addressBook, keysAndCerts);
final AddressBookRoster roster = new AddressBookRoster(addressBook);

final ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
final SerializableDataOutputStream out = new SerializableDataOutputStream(byteOut);
Expand All @@ -58,16 +54,17 @@ void serializeDeserializeTest(
final SerializableDataInputStream in =
new SerializableDataInputStream(new ByteArrayInputStream(byteOut.toByteArray()));

Roster roster2 = in.readSerializable();
final AddressBookRoster roster2 = in.readSerializable();
assertEquals(roster, roster2);
assertEquals(addressBook, roster2.getAddressBook());
}

@Test
@DisplayName("Roster derived from AddressBook")
@ParameterizedTest
@MethodSource({"com.swirlds.platform.crypto.CryptoArgsProvider#basicTestArgs"})
void addressBookRosterTest(
@NonNull final AddressBook addressBook, @NonNull final Map<NodeId, KeysAndCerts> keysAndCerts) {
final Roster roster = new AddressBookRoster(addressBook, keysAndCerts);
void addressBookRosterTest() {
final AddressBook addressBook =
new RandomAddressBookGenerator().setSize(100).build();
final Roster roster = new AddressBookRoster(addressBook);
final Iterator<RosterEntry> entries = roster.iterator();
for (int i = 0; i < addressBook.getSize(); i++) {
final NodeId nodeId = addressBook.getNodeId(i);
Expand All @@ -81,4 +78,28 @@ void addressBookRosterTest(
}
assertFalse(entries.hasNext());
}

@Test
@DisplayName("Serialize and deserialize AddressBook derived Roster")
void serializeDeserializeEntryTest() throws IOException, ConstructableRegistryException {
final AddressBook addressBook =
new RandomAddressBookGenerator().setSize(100).build();
ConstructableRegistry.getInstance().registerConstructables("com.swirlds");
final Roster roster = new AddressBookRoster(addressBook);

for (final RosterEntry entry : roster) {

final ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
final SerializableDataOutputStream out = new SerializableDataOutputStream(byteOut);

out.writeSerializable(entry, true);

final SerializableDataInputStream in =
new SerializableDataInputStream(new ByteArrayInputStream(byteOut.toByteArray()));

RosterEntry entry2 = in.readSerializable();
assertEquals(entry, entry2);
assertEquals(addressBook.getAddress(entry.getNodeId()), ((AddressRosterEntry) entry2).getAddress());
}
}
}

0 comments on commit bf20bc0

Please sign in to comment.