Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

paxe prototype #5

Merged
merged 6 commits into from
Jan 2, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions nodes.txt
Original file line number Diff line number Diff line change
@@ -1,14 +1,23 @@
# tests
mvn -DNO_LOGGING=true -B clean package
mvn clean package

# run just one test
mvn -DskipTests clean package && \
mvn test -Dtest=SRPUtilsTests -pl trex-paxe
mvn test -Dtest=PickleHandshakeTest -pl trex-paxe

# just run subpackage tests
mvn -DskipTests clean package && \
mvn test -pl trex-paxe

# run just one test method
mvn test -pl trex-paxe -Dtest=com.github.trex_paxos.paxe.PaxeNetworkTest#testStartup

# run just one test fine logging
clear ; mvn test -Dtest=com.github.trex_paxos.paxe.PaxeNetworkTest#testStartup -Djava.util.logging.ConsoleHandler.level=FINEST

# run just one test class fine logging
clear ; mvn test -pl trex-paxe -Dtest=com.github.trex_paxos.paxe.PaxeNetworkTest -Djava.util.logging.ConsoleHandler.level=FINEST

# Grab the files for LLM

rm all.java
Expand Down
32 changes: 25 additions & 7 deletions trex-lib/src/test/java/com/github/trex_paxos/SimulationTests.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
import com.github.trex_paxos.msg.BroadcastMessage;
import com.github.trex_paxos.msg.DirectMessage;
import com.github.trex_paxos.msg.TrexMessage;

import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;

import java.util.ArrayList;
Expand All @@ -27,6 +29,7 @@
import java.util.concurrent.atomic.AtomicLong;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.logging.ConsoleHandler;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.random.RandomGenerator;
Expand All @@ -39,13 +42,28 @@

public class SimulationTests {

static {
if (System.getProperty("NO_LOGGING") != null && System.getProperty("NO_LOGGING").equals("true")) {
Logger.getLogger("").setLevel(Level.OFF);
} else {
LoggerConfig.initialize();
}
}
@BeforeAll
static void setupLogging() {

final var logLevel = System.getProperty("java.util.logging.ConsoleHandler.level", "WARNING");
final Level level = Level.parse(logLevel);

LOGGER.setLevel(level);
ConsoleHandler consoleHandler = new ConsoleHandler();
consoleHandler.setLevel(level);
LOGGER.addHandler(consoleHandler);

// Configure SessionKeyManager logger
Logger sessionKeyManagerLogger = Logger.getLogger("");
sessionKeyManagerLogger.setLevel(level);
ConsoleHandler skmHandler = new ConsoleHandler();
skmHandler.setLevel(level);
sessionKeyManagerLogger.addHandler(skmHandler);

// Optionally disable parent handlers if needed
LOGGER.setUseParentHandlers(false);
sessionKeyManagerLogger.setUseParentHandlers(false);
}

@Test
public void testLeaderElection1000() {
Expand Down
89 changes: 61 additions & 28 deletions trex-lib/src/test/java/com/github/trex_paxos/SpecificTests.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,22 +17,41 @@

import com.github.trex_paxos.TrexNode.TrexRole;
import com.github.trex_paxos.msg.*;

import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;

import java.util.List;
import java.util.logging.ConsoleHandler;
import java.util.logging.Level;
import java.util.logging.Logger;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static com.github.trex_paxos.Simulation.LOGGER;

public class SpecificTests {
static {
if (System.getProperty("NO_LOGGING") != null && System.getProperty("NO_LOGGING").equals("true")) {
Logger.getLogger("").setLevel(Level.OFF);
} else {
LoggerConfig.initialize();
}
@BeforeAll
static void setupLogging() {

final var logLevel = System.getProperty("java.util.logging.ConsoleHandler.level", "WARNING");
final Level level = Level.parse(logLevel);

LOGGER.setLevel(level);
ConsoleHandler consoleHandler = new ConsoleHandler();
consoleHandler.setLevel(level);
LOGGER.addHandler(consoleHandler);

// Configure SessionKeyManager logger
Logger sessionKeyManagerLogger = Logger.getLogger("");
sessionKeyManagerLogger.setLevel(level);
ConsoleHandler skmHandler = new ConsoleHandler();
skmHandler.setLevel(level);
sessionKeyManagerLogger.addHandler(skmHandler);

// Optionally disable parent handlers if needed
LOGGER.setUseParentHandlers(false);
sessionKeyManagerLogger.setUseParentHandlers(false);
}

final QuorumStrategy threeNodeQuorum = new SimpleMajority(3);
Expand All @@ -47,18 +66,24 @@ public class SpecificTests {
@Test
public void testCatchupDoesNotViolateInvariantsYetDoesLearnDespiteHigherSelfPromise() {

// Given that node 1 has accepted a value at slot 1 and has made a very high self promise
// Given that node 1 has accepted a value at slot 1 and has made a very high
// self promise
final var nodeId1 = (short) 1;
final var journal = new TransparentJournal((short) 1);
final var acceptPreviouslyFixedSlot1 = new Accept((short) 1, 1L, new BallotNumber(1, (short) 1), new Command( "data".getBytes()));
final var acceptPreviouslyFixedSlot1 = new Accept((short) 1, 1L, new BallotNumber(1, (short) 1),
new Command("data".getBytes()));
final var higherSelfPromiseNumber = new BallotNumber(1000, (short) 1);
TrexNode node = new TrexNode(Level.INFO, nodeId1, threeNodeQuorum, journal) {{
this.journal.writeAccept(acceptPreviouslyFixedSlot1);
this.progress = new Progress(nodeIdentifier, higherSelfPromiseNumber, 1L);
}};

// When node 2 sends a catchup response that has fixed values made under a previous leaders ballot number
// And where the actual fixed message at slot one is different to the one that node 1 thinks is already fixed.
TrexNode node = new TrexNode(Level.INFO, nodeId1, threeNodeQuorum, journal) {
{
this.journal.writeAccept(acceptPreviouslyFixedSlot1);
this.progress = new Progress(nodeIdentifier, higherSelfPromiseNumber, 1L);
}
};

// When node 2 sends a catchup response that has fixed values made under a
// previous leaders ballot number
// And where the actual fixed message at slot one is different to the one that
// node 1 thinks is already fixed.
final var nodeId2 = (short) 2;
final var ballotNumber2 = new BallotNumber(2, (short) 2);
final var ignoreAcceptSlot1 = new Accept(nodeId2, 1L, ballotNumber2, new Command("data2".getBytes()));
Expand All @@ -69,11 +94,15 @@ public void testCatchupDoesNotViolateInvariantsYetDoesLearnDespiteHigherSelfProm
node.paxos(catchUpResponse);

// Then the fixed value should not have changed after processing the catchup.
assertEquals(acceptPreviouslyFixedSlot1, journal.fakeJournal.get(1L), "The fixed value should not have changed after processing the catchup.");
// And the node should accept the second slot value even having made a higher self-promise
assertEquals(freshAcceptSlot2, journal.fakeJournal.get(2L), "The node should accepted the second slot value even having made a higher self-promise");
// And the node should not have updated its progress ballot number
assertEquals(higherSelfPromiseNumber, node.progress.highestPromised(), "The node should not have updated its progress to the new ballot number");
assertEquals(acceptPreviouslyFixedSlot1, journal.fakeJournal.get(1L),
"The fixed value should not have changed after processing the catchup.");
// And the node should accept the second slot value even having made a higher
// self-promise
assertEquals(freshAcceptSlot2, journal.fakeJournal.get(2L),
"The node should accepted the second slot value even having made a higher self-promise");
// And the node should not have updated its progress ballot number
assertEquals(higherSelfPromiseNumber, node.progress.highestPromised(),
"The node should not have updated its progress to the new ballot number");
// And the node should have updated the progress fixed index
assertEquals(2L, node.progress.highestFixedIndex(), "The node should have updated the progress fixed index");
}
Expand All @@ -89,13 +118,16 @@ public void testCatchupWithHigherBallotNumberAndLowerFixedSlotCausesLeaderToIncr
final var nodeId1 = (short) 1;
final var originalNumber = new BallotNumber(1, nodeId1);
final var journal = new TransparentJournal(nodeId1);
final var acceptPreviouslyFixedSlot1 = new Accept((short) 1, 1L, new BallotNumber(1, (short) 1), new Command( "data".getBytes()));
TrexNode node = new TrexNode(Level.INFO, nodeId1, threeNodeQuorum, journal) {{
this.progress = new Progress(nodeIdentifier, originalNumber, 1L);
this.journal.writeAccept(acceptPreviouslyFixedSlot1);
this.setRole(TrexRole.LEAD);
this.term = originalNumber;
}};
final var acceptPreviouslyFixedSlot1 = new Accept((short) 1, 1L, new BallotNumber(1, (short) 1),
new Command("data".getBytes()));
TrexNode node = new TrexNode(Level.INFO, nodeId1, threeNodeQuorum, journal) {
{
this.progress = new Progress(nodeIdentifier, originalNumber, 1L);
this.journal.writeAccept(acceptPreviouslyFixedSlot1);
this.setRole(TrexRole.LEAD);
this.term = originalNumber;
}
};

assert node.progress.highestPromised().equals(originalNumber);

Expand All @@ -118,5 +150,6 @@ public void testCatchupWithHigherBallotNumberAndLowerFixedSlotCausesLeaderToIncr

// FIXME make sure you test explicitly all the abdication scenarios

// FIXME other tests around making sure fixed messages are issued for every accept
// FIXME other tests around making sure fixed messages are issued for every
// accept
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@

public record Channel(byte value) {
public static final byte CONSENSUS = 0;

public Channel {
if (value < 0) throw new IllegalArgumentException("Channel must be non-negative");
}
public static final byte KEY_EXCHANGE = (byte)255;
static final Channel CONSENSUS_CHANNEL = new Channel(CONSENSUS);
static final Channel KEY_EXCHANGE_CHANNEL = new Channel(KEY_EXCHANGE);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.github.trex_paxos.paxe;

public record ClusterId(String id) {
public ClusterId {
if(id == null) {
throw new IllegalArgumentException("id required");
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.github.trex_paxos.paxe;

import java.util.Objects;

public record NodeClientSecret(
String srpIdenity,
String password,
byte[] salt // 16 bytes required
) {
public NodeClientSecret {
Objects.requireNonNull(srpIdenity, "srpIdenity required");
Objects.requireNonNull(password, "password required");
Objects.requireNonNull(salt, "salt required");
if(salt.length != 16) {
throw new IllegalArgumentException("salt must be 16 bytes");
}
}
public NodeClientSecret(ClusterId clusterId, NodeId id, String password, byte[] salt) {
this(id.id() + "@" + clusterId.id(), password, salt);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.github.trex_paxos.paxe;

import java.util.Objects;

/// A verifier for a node in the cluster
/// @param identity RFC 5054 identity which is the node id and cluster id concatenated with '@' such as "[email protected]"
/// @param verifier RFC 5054 verifier as hex string
public record NodeVerifier(
String identity,
String verifier
) {
public NodeVerifier {
Objects.requireNonNull(identity, "identity required");
Objects.requireNonNull(verifier, "verifier required");
}
}
Loading
Loading