From 9735afb5f8b1af7745e9cc4ed1199a71ac40dfc8 Mon Sep 17 00:00:00 2001 From: Hellblazer Date: Sat, 27 Jan 2024 14:52:23 -0800 Subject: [PATCH] validate agreement on diadem between joining and current validator --- .../com/salesforce/apollo/choam/CHOAM.java | 20 +++++++++++++++---- .../salesforce/apollo/choam/ViewAssembly.java | 10 +++++++++- .../salesforce/apollo/choam/ViewContext.java | 2 +- .../apollo/choam/ViewAssemblyTest.java | 1 + .../apollo/bloomFilters/BloomFilter.java | 5 +++-- .../apollo/cryptography/HexBloom.java | 7 +++---- .../apollo/membership/GroupIterator.java | 20 ++++++++++--------- 7 files changed, 44 insertions(+), 21 deletions(-) diff --git a/choam/src/main/java/com/salesforce/apollo/choam/CHOAM.java b/choam/src/main/java/com/salesforce/apollo/choam/CHOAM.java index 32eb052f84..9c88885387 100644 --- a/choam/src/main/java/com/salesforce/apollo/choam/CHOAM.java +++ b/choam/src/main/java/com/salesforce/apollo/choam/CHOAM.java @@ -638,7 +638,6 @@ private void nextView() { params.member().getId()); next.set(new nextView(ViewMember.newBuilder() .setId(params.member().getId().toDigeste()) - .setDiadem(current.toHexBloome()) .setConsensusKey(pubKey) .setSignature(signed.toSig()) .build(), keyPair)); @@ -1160,7 +1159,7 @@ public ViewMember join(Digest nextView, Digest from) { log.debug("Joining view: {} from: {} view member: {} on: {}", nextView, from, ViewContext.print(c.member, params.digestAlgorithm()), params.member().getId()); } - return c.member; + return ViewMember.newBuilder(c.member).setDiadem(diadem.get().toIdentityHexBloome()).build(); } @Override @@ -1175,6 +1174,14 @@ public Parameters params() { @Override public SubmitResult submitTxn(Transaction transaction) { + if (!servers.hasNext()) { + log.trace("Failed submitting txn: {} no servers available in: {} on: {}", + hashOf(transaction, params.digestAlgorithm()), viewId, params.member().getId()); + return SubmitResult.newBuilder() + .setResult(Result.ERROR_SUBMITTING) + .setErrorMsg("no servers available") + .build(); + } Member target = servers.next(); try (var link = submissionComm.connect(target)) { if (link == null) { @@ -1299,11 +1306,16 @@ public ViewMember join(Digest nextView, Digest from) { return ViewMember.getDefaultInstance(); } final var c = next.get(); + var cd = diadem.get(); + assert cd.equivalent(HexBloom.from(cd.toIdentityHexBloome())) : "Deser: {} not equal to: {}".formatted( + HexBloom.from(cd.toIdentityHexBloome()), cd); if (log.isDebugEnabled()) { - log.debug("Joining view: {} from: {} view member: {} on: {}", nextView, from, + log.debug("Joining view: {} diadem: {} from: {} view member: {} on: {}", nextView, cd, from, ViewContext.print(c.member, params.digestAlgorithm()), params.member().getId()); } - return c.member; + var vm = ViewMember.newBuilder(c.member).setDiadem(cd.toIdentityHexBloome()).build(); + assert vm.hasDiadem() && vm.getDiadem().hasMembership(); + return vm; } @Override diff --git a/choam/src/main/java/com/salesforce/apollo/choam/ViewAssembly.java b/choam/src/main/java/com/salesforce/apollo/choam/ViewAssembly.java index c4bf544c8c..bf09165016 100644 --- a/choam/src/main/java/com/salesforce/apollo/choam/ViewAssembly.java +++ b/choam/src/main/java/com/salesforce/apollo/choam/ViewAssembly.java @@ -14,6 +14,7 @@ import com.salesforce.apollo.choam.fsm.Reconfiguration.Transitions; import com.salesforce.apollo.choam.proto.*; import com.salesforce.apollo.cryptography.Digest; +import com.salesforce.apollo.cryptography.HexBloom; import com.salesforce.apollo.cryptography.proto.PubKey; import com.salesforce.apollo.membership.Member; import com.salesforce.apollo.ring.SliceIterator; @@ -167,6 +168,7 @@ private boolean consider(Optional futureSailor, Terminal term, Membe log.debug("Empty join response from: {} on: {}", term.getMember().getId(), params().member().getId()); return !gathered(); } + assert member.hasDiadem() && member.getDiadem().hasMembership(); var vm = new Digest(member.getId()); if (!m.getId().equals(vm)) { log.debug("Invalid join response from: {} expected: {} on: {}", term.getMember().getId(), vm, @@ -198,7 +200,13 @@ private Reassemble join(ViewMember vm) { } return null; } - + final var hex = HexBloom.from(vm.getDiadem()); + var diadem = view.diadem(); + if (!diadem.equivalent(hex)) { + log.warn("Invalid diadem: {} not equivalent to: {} vm: {} on: {}", hex.compact(), diadem.compact(), + ViewContext.print(vm, params().digestAlgorithm()), params().member().getId()); + return null; + } PubKey encoded = vm.getConsensusKey(); if (!m.verify(signature(vm.getSignature()), encoded.toByteString())) { diff --git a/choam/src/main/java/com/salesforce/apollo/choam/ViewContext.java b/choam/src/main/java/com/salesforce/apollo/choam/ViewContext.java index 9bb91c43c4..bedbeb5533 100644 --- a/choam/src/main/java/com/salesforce/apollo/choam/ViewContext.java +++ b/choam/src/main/java/com/salesforce/apollo/choam/ViewContext.java @@ -75,7 +75,7 @@ public Context context() { } public HexBloom diadem() { - return blockProducer.diadem(); + return blockProducer == null ? new HexBloom() : blockProducer.diadem(); } public Validate generateValidation(HashedBlock block) { diff --git a/choam/src/test/java/com/salesforce/apollo/choam/ViewAssemblyTest.java b/choam/src/test/java/com/salesforce/apollo/choam/ViewAssemblyTest.java index 2350f783ee..55db2e1579 100644 --- a/choam/src/test/java/com/salesforce/apollo/choam/ViewAssemblyTest.java +++ b/choam/src/test/java/com/salesforce/apollo/choam/ViewAssemblyTest.java @@ -130,6 +130,7 @@ private void buildAssemblies() { public ViewMember answer(InvocationOnMock invocation) throws Throwable { return ViewMember.newBuilder() .setId(m.getId().toDigeste()) + .setDiadem(new HexBloom().toIdentityHexBloome()) .setConsensusKey(consensus) .setSignature(((Signer) m).sign(consensus.toByteString()).toSig()) .build(); diff --git a/cryptography/src/main/java/com/salesforce/apollo/bloomFilters/BloomFilter.java b/cryptography/src/main/java/com/salesforce/apollo/bloomFilters/BloomFilter.java index 6208126651..d452b07747 100644 --- a/cryptography/src/main/java/com/salesforce/apollo/bloomFilters/BloomFilter.java +++ b/cryptography/src/main/java/com/salesforce/apollo/bloomFilters/BloomFilter.java @@ -6,8 +6,8 @@ */ package com.salesforce.apollo.bloomFilters; -import com.salesforce.apollo.cryptography.proto.Biff; import com.salesforce.apollo.cryptography.Digest; +import com.salesforce.apollo.cryptography.proto.Biff; import org.joou.ULong; import java.util.BitSet; @@ -116,7 +116,8 @@ public boolean contains(T element) { } public boolean equivalent(BloomFilter other) { - return h.equivalent(other.h) && bits.equals(other.bits); + var equiv = h.equivalent(other.h) && bits.equals(other.bits); + return equiv; } public double fpp(int n) { diff --git a/cryptography/src/main/java/com/salesforce/apollo/cryptography/HexBloom.java b/cryptography/src/main/java/com/salesforce/apollo/cryptography/HexBloom.java index 22501db875..90714cf0d6 100644 --- a/cryptography/src/main/java/com/salesforce/apollo/cryptography/HexBloom.java +++ b/cryptography/src/main/java/com/salesforce/apollo/cryptography/HexBloom.java @@ -57,10 +57,8 @@ public HexBloom(Digest initial, List> hashes) { } public HexBloom(HexBloome hb) { - this(hb.getCardinality(), - hb.getCrownsList().isEmpty() ? Collections.singletonList(DigestAlgorithm.DEFAULT.getLast()) - : hb.getCrownsList().stream().map(d -> Digest.from(d)).toList(), - hb.hasMembership() ? BloomFilter.from(hb.getMembership()) : new BloomFilter.DigestBloomFilter(0, 1, 0.1)); + this(hb.getCardinality(), hb.getCrownsList().stream().map(d -> Digest.from(d)).toList(), + BloomFilter.from(hb.getMembership())); } public HexBloom(int cardinality, List crowns, BloomFilter membership) { @@ -246,6 +244,7 @@ public static HexBloom construct(List currentMembership, List ad } public static HexBloom from(HexBloome hb) { + assert !HexBloome.getDefaultInstance().equals(hb); return new HexBloom(hb); } diff --git a/memberships/src/main/java/com/salesforce/apollo/membership/GroupIterator.java b/memberships/src/main/java/com/salesforce/apollo/membership/GroupIterator.java index cb580cdd6e..a94bc9b6bd 100644 --- a/memberships/src/main/java/com/salesforce/apollo/membership/GroupIterator.java +++ b/memberships/src/main/java/com/salesforce/apollo/membership/GroupIterator.java @@ -6,29 +6,31 @@ */ package com.salesforce.apollo.membership; +import com.salesforce.apollo.utils.Entropy; + import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.concurrent.Semaphore; -import com.salesforce.apollo.utils.Entropy; - /** - * Simple iterator on a group of members, randomly shuffling the membership list - * after each complete iteration - * - * @author hal.hildebrand + * Simple iterator on a group of members, randomly shuffling the membership list after each complete iteration * + * @author hal.hildebrand */ public class GroupIterator { - private volatile int current = 0; - private final List group; - private final Semaphore exclusive = new Semaphore(1); + private final List group; + private final Semaphore exclusive = new Semaphore(1); + private volatile int current = 0; public GroupIterator(Collection group) { this.group = new ArrayList<>(group); } + public boolean hasNext() { + return !group.isEmpty(); + } + public Member next() { exclusive.acquireUninterruptibly(); try {