Skip to content

Commit

Permalink
Validate crown upon checkpoint assembly
Browse files Browse the repository at this point in the history
  • Loading branch information
Hellblazer committed Nov 18, 2023
1 parent c9a8f8b commit 023ea06
Show file tree
Hide file tree
Showing 6 changed files with 146 additions and 125 deletions.
18 changes: 6 additions & 12 deletions choam/src/main/java/com/salesforce/apollo/choam/CHOAM.java
Original file line number Diff line number Diff line change
Expand Up @@ -136,15 +136,8 @@ public CHOAM(Parameters params) {
}

public static Checkpoint checkpoint(DigestAlgorithm algo, File state, int segmentSize, Digest initialCrown) {
Digest stateHash = algo.getOrigin();
long length = 0;
if (state != null) {
try (FileInputStream fis = new FileInputStream(state)) {
stateHash = algo.digest(fis);
} catch (IOException e) {
log.error("Invalid checkpoint!", e);
return null;
}
length = state.length();
}
Checkpoint.Builder builder = Checkpoint.newBuilder().setByteSize(length).setSegmentSize(segmentSize);
Expand All @@ -160,12 +153,13 @@ public static Checkpoint checkpoint(DigestAlgorithm algo, File state, int segmen
return null;
}
}
log.info("Checkpoint length: {} segment size: {} count: {} stateHash: {}", length, segmentSize,
builder.getSegmentsCount(), stateHash);

return builder.setCrown(
HexBloom.construct(builder.getSegmentsCount(), builder.getSegmentsList().stream().map(d -> Digest.from(d)),
initialCrown, 2).toHexBloome()).build();
var crown = HexBloom.construct(builder.getSegmentsCount(),
builder.getSegmentsList().stream().map(d -> Digest.from(d)), initialCrown, 2)
.compactWrapped();
log.info("Checkpoint length: {} segment size: {} count: {} crown: {}", length, segmentSize,
builder.getSegmentsCount(), crown);
return builder.setCrown(crown.toDigeste()).build();
}

public static Block genesis(Digest id, Map<Member, Join> joins, HashedBlock head, Context<Member> context,
Expand Down
17 changes: 13 additions & 4 deletions choam/src/main/java/com/salesforce/apollo/choam/Parameters.java
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
*/
public record Parameters(Parameters.RuntimeParameters runtime, ReliableBroadcaster.Parameters combine,
Duration gossipDuration, int maxCheckpointSegments, Duration submitTimeout,
Digest genesisViewId, int checkpointBlockDelta, DigestAlgorithm digestAlgorithm,
Digest genesisViewId, int checkpointBlockDelta, int crowns, DigestAlgorithm digestAlgorithm,
SignatureAlgorithm viewSigAlgorithm, int synchronizationCycles, int regenerationCycles,
Parameters.BootstrapParameters bootstrap, Parameters.ProducerParameters producer,
Parameters.MvStoreBuilder mvBuilder, Parameters.LimiterBuilder txnLimiterBuilder,
Expand Down Expand Up @@ -677,12 +677,21 @@ public static class Builder implements Cloneable {
private int synchronizationCycles = 10;
private LimiterBuilder txnLimiterBuilder = new LimiterBuilder();
private SignatureAlgorithm viewSigAlgorithm = SignatureAlgorithm.DEFAULT;
private int crowns = 2;

public int getCrowns() {
return crowns;
}

public void setCrowns(int crowns) {
this.crowns = crowns;
}

public Parameters build(RuntimeParameters runtime) {
return new Parameters(runtime, combine, gossipDuration, maxCheckpointSegments, submitTimeout, genesisViewId,
checkpointBlockDelta, digestAlgorithm, viewSigAlgorithm, synchronizationCycles,
regenerationCycles, bootstrap, producer, mvBuilder, txnLimiterBuilder, submitPolicy,
checkpointSegmentSize, drainPolicy);
checkpointBlockDelta, crowns, digestAlgorithm, viewSigAlgorithm,
synchronizationCycles, regenerationCycles, bootstrap, producer, mvBuilder,
txnLimiterBuilder, submitPolicy, checkpointSegmentSize, drainPolicy);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,19 @@
import com.google.common.collect.TreeMultiset;
import com.salesfoce.apollo.choam.proto.*;
import com.salesforce.apollo.archipelago.RouterImpl.CommonCommunications;
import com.salesforce.apollo.bloomFilters.BloomFilter;
import com.salesforce.apollo.bloomFilters.BloomFilter.ULongBloomFilter;
import com.salesforce.apollo.choam.Parameters;
import com.salesforce.apollo.choam.comm.Concierge;
import com.salesforce.apollo.choam.comm.Terminal;
import com.salesforce.apollo.crypto.Digest;
import com.salesforce.apollo.crypto.DigestAlgorithm;
import com.salesforce.apollo.crypto.HexBloom;
import com.salesforce.apollo.membership.Member;
import com.salesforce.apollo.ring.RingCommunications;
import com.salesforce.apollo.ring.RingIterator;
import com.salesforce.apollo.utils.Entropy;
import com.salesforce.apollo.utils.Pair;
import com.salesforce.apollo.bloomFilters.BloomFilter;
import com.salesforce.apollo.bloomFilters.BloomFilter.ULongBloomFilter;
import org.joou.ULong;
import org.joou.Unsigned;
import org.slf4j.Logger;
Expand Down Expand Up @@ -134,6 +135,7 @@ private void checkpointCompletion(int threshold, Initial mostRecent) {

// assemble the checkpoint
checkpointAssembled = assembler.assemble(scheduler, params.gossipDuration()).whenComplete((cps, t) -> {
validate(cps);
log.info("Restored checkpoint: {} on: {}", checkpoint.height(), params.member().getId());
checkpointState = cps;
});
Expand All @@ -148,6 +150,22 @@ private void checkpointCompletion(int threshold, Initial mostRecent) {
scheduleViewChainCompletion(new AtomicReference<>(checkpointView.height()), ULong.valueOf(0));
}

private void validate(CheckpointState cps) {
var crown = HexBloom.construct(cps.checkpoint.getSegmentsCount(),
cps.checkpoint.getSegmentsList().stream().map(d -> Digest.from(d)),
Digest.from(checkpoint.block.getHeader().getLastCheckpointHash()),
params.crowns());
var have = crown.compactWrapped();
var expected = Digest.from(cps.checkpoint.getCrown());
if (!have.equals(expected)) {
log.error("Invalid crown for checkpointed state have: {} expected: {} on: {}", have, expected,
params.member());
throw new IllegalStateException(
"Invalid crown for checkpointed state have: %s expected: %s on: %s".formatted(have, expected,
params.member()));
}
}

private boolean completeAnchor(Optional<Blocks> futureSailor, AtomicReference<ULong> start, ULong end,
RingCommunications.Destination<Member, Terminal> destination) {
if (sync.isDone() || anchorSynchronized.isDone()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import com.salesfoce.apollo.choam.proto.CheckpointReplication;
import com.salesfoce.apollo.choam.proto.CheckpointSegments;
import com.salesforce.apollo.archipelago.RouterImpl.CommonCommunications;
import com.salesforce.apollo.bloomFilters.BloomFilter;
import com.salesforce.apollo.choam.comm.Concierge;
import com.salesforce.apollo.choam.comm.Terminal;
import com.salesforce.apollo.crypto.Digest;
Expand All @@ -19,7 +20,6 @@
import com.salesforce.apollo.membership.SigningMember;
import com.salesforce.apollo.ring.RingIterator;
import com.salesforce.apollo.utils.Entropy;
import com.salesforce.apollo.bloomFilters.BloomFilter;
import org.h2.mvstore.MVMap;
import org.joou.ULong;
import org.slf4j.Logger;
Expand Down Expand Up @@ -71,8 +71,8 @@ public CheckpointAssembler(Duration frequency, ULong height, Checkpoint checkpoi

public CompletableFuture<CheckpointState> assemble(ScheduledExecutorService scheduler, Duration duration) {
if (checkpoint.getSegmentsCount() == 0) {
log.info("Assembled checkpoint: {} segments: {} on: {}", height, checkpoint.getSegmentsCount(),
member.getId());
log.info("Assembled checkpoint: {} segments: {} crown: {} on: {}", height, checkpoint.getSegmentsCount(),
Digest.from(checkpoint.getCrown()), member.getId());
assembled.complete(new CheckpointState(checkpoint, state));
} else {
gossip(scheduler, duration);
Expand All @@ -98,8 +98,8 @@ private boolean gossip(Optional<CheckpointSegments> futureSailor) {
}
if (process(futureSailor.get())) {
CheckpointState cs = new CheckpointState(checkpoint, state);
log.info("Assembled checkpoint: {} segments: {} on: {}", height, checkpoint.getSegmentsCount(),
member.getId());
log.info("Assembled checkpoint: {} segments: {} crown: {} on: {}", height, checkpoint.getSegmentsCount(),
Digest.from(checkpoint.getCrown()), member.getId());
assembled.complete(cs);
return false;
}
Expand All @@ -110,8 +110,8 @@ private void gossip(ScheduledExecutorService scheduler, Duration duration) {
if (assembled.isDone()) {
return;
}
log.info("Assembly of checkpoint: {} segments: {} on: {}", height, checkpoint.getSegmentsCount(),
member.getId());
log.info("Assembly of checkpoint: {} segments: {} crown: {} on: {}", height, checkpoint.getSegmentsCount(),
Digest.from(checkpoint.getCrown()), member.getId());
var ringer = new RingIterator<>(frequency, context, member, comms, true, scheduler);
ringer.iterate(randomCut(digestAlgorithm), (link, ring) -> gossip(link),
(tally, result, destination) -> gossip(result),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -367,7 +367,7 @@ public HexBloome toIdentityHexBloome() {

@Override
public String toString() {
return crowns().toString();
return "HexBloom%s".formatted(crowns().toString());
}

/**
Expand Down
Loading

0 comments on commit 023ea06

Please sign in to comment.