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 3c25f67a4..32eb052f8 100644 --- a/choam/src/main/java/com/salesforce/apollo/choam/CHOAM.java +++ b/choam/src/main/java/com/salesforce/apollo/choam/CHOAM.java @@ -92,7 +92,7 @@ public class CHOAM { public CHOAM(Parameters params) { this.store = new Store(params.digestAlgorithm(), params.mvBuilder().clone().build()); this.params = params; - diadem.set(new HexBloom(params.digestAlgorithm().getLast(), 0)); + diadem.set(new HexBloom(params.digestAlgorithm().getLast())); executions = Executors.newVirtualThreadPerTaskExecutor(); nextView(); @@ -300,6 +300,7 @@ public String logState() { } public void setDiadem(HexBloom diadem) { + log.info("Set diadem: {} on: {}", diadem.compact(), params.member().getId()); this.diadem.set(diadem); } @@ -307,7 +308,8 @@ public void start() { if (!started.compareAndSet(false, true)) { return; } - log.info("CHOAM startup, majority: {} on: {}", params.majority(), params.member().getId()); + log.info("CHOAM startup: {} diadem: {}, majority: {} on: {}", params.context().getId(), diadem.get().compact(), + params.majority(), params.member().getId()); combine.start(params.producer().gossipDuration()); transitions.fsm().enterStartState(); transitions.start(); @@ -472,33 +474,40 @@ public Block checkpoint() { return CHOAM.this.checkpoint(); } + @Override + public HexBloom diadem() { + return diadem.get(); + } + @Override public Block genesis(Map joining, Digest nextViewId, HashedBlock previous) { final HashedCertifiedBlock cp = checkpoint.get(); final HashedCertifiedBlock v = view.get(); - return CHOAM.genesis(nextViewId, diadem.get(), joining, previous, params.context(), v, params, cp, + var current = diadem.get(); + log.info("Create genesis: {}", diadem.get().compact()); + return CHOAM.genesis(nextViewId, current, joining, previous, params.context(), v, params, cp, params.genesisData().apply(joining)); } @Override - public Block produce(ULong height, Digest prev, Assemble assemble, HashedBlock checkpoint) { + public Block produce(ULong height, Digest prev, Executions executions, HashedBlock checkpoint) { final HashedCertifiedBlock v = view.get(); return Block.newBuilder() .setHeader( - buildHeader(params.digestAlgorithm(), assemble, prev, height, checkpoint.height(), + buildHeader(params.digestAlgorithm(), executions, prev, height, checkpoint.height(), checkpoint.hash, v.height(), v.hash)) - .setAssemble(assemble) + .setExecutions(executions) .build(); } @Override - public Block produce(ULong height, Digest prev, Executions executions, HashedBlock checkpoint) { + public Block produce(ULong height, Digest prev, Assemble assemble, HashedBlock checkpoint) { final HashedCertifiedBlock v = view.get(); return Block.newBuilder() .setHeader( - buildHeader(params.digestAlgorithm(), executions, prev, height, checkpoint.height(), + buildHeader(params.digestAlgorithm(), assemble, prev, height, checkpoint.height(), checkpoint.hash, v.height(), v.hash)) - .setExecutions(executions) + .setAssemble(assemble) .build(); } @@ -625,7 +634,8 @@ private void nextView() { var current = diadem.get(); log.trace("Generated next view consensus key: {} sig: {} diadem: {} on: {}", params.digestAlgorithm().digest(pubKey.getEncoded()), - params.digestAlgorithm().digest(signed.toSig().toByteString()), current, params.member().getId()); + params.digestAlgorithm().digest(signed.toSig().toByteString()), current.compact(), + params.member().getId()); next.set(new nextView(ViewMember.newBuilder() .setId(params.member().getId().toDigeste()) .setDiadem(current.toHexBloome()) @@ -643,9 +653,15 @@ private void process() { case ASSEMBLE: { params.processor().beginBlock(h.height(), h.hash); nextViewId.set(Digest.from(h.block.getAssemble().getNextView())); - var diadem = HexBloom.from(h.block.getAssemble().getDiadem()); - log.info("Next view id: {} diadem: {} on: {}", nextViewId.get(), diadem.compact(), params.member().getId()); - c.assembled(diadem); + var ass = HexBloom.from(h.block.getAssemble().getDiadem()); + var current = diadem.getAndSet(ass); + if (!current.equivalent(ass)) { + log.info("Next view id: {} diadem: {} does match current: {} on: {}", nextViewId.get(), ass.compact(), + current.compact(), params.member().getId()); + } + log.info("Next view id: {} diadem: {} on: {}", nextViewId.get(), diadem.get().compact(), + params.member().getId()); + c.assembled(); break; } case RECONFIGURE: { @@ -948,12 +964,14 @@ private void synchronizedProcess(CertifiedBlock certifiedBlock) { public interface BlockProducer { Block checkpoint(); - Block genesis(Map joining, Digest nextViewId, HashedBlock previous); + HexBloom diadem(); - Block produce(ULong height, Digest prev, Assemble assemble, HashedBlock checkpoint); + Block genesis(Map joining, Digest nextViewId, HashedBlock previous); Block produce(ULong height, Digest prev, Executions executions, HashedBlock checkpoint); + Block produce(ULong height, Digest prev, Assemble assemble, HashedBlock checkpoint); + void publish(CertifiedBlock cb); Block reconfigure(Map joining, Digest nextViewId, HashedBlock previous, HashedBlock checkpoint); @@ -1201,15 +1219,14 @@ private class Associate extends Administration { params.digestAlgorithm().digest(nextView.member.getSignature().toByteString()), viewId, params.member().getId()); Signer signer = new SignerImpl(nextView.consensusKeyPair.getPrivate(), ULong.MIN); - producer = new Producer( - new ViewContext(context, () -> diadem.get(), params, signer, validators, constructBlock()), head.get(), - checkpoint.get(), comm, getLabel()); + producer = new Producer(new ViewContext(context, params, signer, validators, constructBlock()), head.get(), + checkpoint.get(), comm, getLabel()); producer.start(); } @Override - public void assembled(HexBloom diadem) { - producer.assembled(diadem); + public void assembled() { + producer.assembled(); } @Override @@ -1245,7 +1262,7 @@ private Formation() { params.digestAlgorithm().digest(c.member.getSignature().toByteString()), params.member().getId()); Signer signer = new SignerImpl(c.consensusKeyPair.getPrivate(), ULong.MIN); - ViewContext vc = new GenesisContext(formation, () -> diadem.get(), params, signer, constructBlock()); + ViewContext vc = new GenesisContext(formation, params, signer, constructBlock()); assembly = new GenesisAssembly(vc, comm, next.get().member, getLabel()); nextViewId.set(params.genesisViewId()); } else { diff --git a/choam/src/main/java/com/salesforce/apollo/choam/Committee.java b/choam/src/main/java/com/salesforce/apollo/choam/Committee.java index 48ba32b8f..acd13df04 100644 --- a/choam/src/main/java/com/salesforce/apollo/choam/Committee.java +++ b/choam/src/main/java/com/salesforce/apollo/choam/Committee.java @@ -9,7 +9,10 @@ import com.salesforce.apollo.choam.proto.*; import com.salesforce.apollo.choam.proto.SubmitResult.Result; import com.salesforce.apollo.choam.support.HashedCertifiedBlock; -import com.salesforce.apollo.cryptography.*; +import com.salesforce.apollo.cryptography.Digest; +import com.salesforce.apollo.cryptography.DigestAlgorithm; +import com.salesforce.apollo.cryptography.JohnHancock; +import com.salesforce.apollo.cryptography.Verifier; import com.salesforce.apollo.cryptography.Verifier.DefaultVerifier; import com.salesforce.apollo.membership.Context; import com.salesforce.apollo.membership.ContextImpl; @@ -60,7 +63,7 @@ static Set viewMembersOf(Digest hash, Context baseContex void accept(HashedCertifiedBlock next); - default void assembled(HexBloom diadem) { + default void assembled() { } void complete(); diff --git a/choam/src/main/java/com/salesforce/apollo/choam/GenesisContext.java b/choam/src/main/java/com/salesforce/apollo/choam/GenesisContext.java index 17fdfd734..fc8d5bca9 100644 --- a/choam/src/main/java/com/salesforce/apollo/choam/GenesisContext.java +++ b/choam/src/main/java/com/salesforce/apollo/choam/GenesisContext.java @@ -8,23 +8,20 @@ import com.salesforce.apollo.choam.CHOAM.BlockProducer; import com.salesforce.apollo.choam.proto.Validate; -import com.salesforce.apollo.cryptography.HexBloom; import com.salesforce.apollo.cryptography.Signer; import com.salesforce.apollo.cryptography.Verifier; import com.salesforce.apollo.membership.Context; import com.salesforce.apollo.membership.Member; import java.util.Collections; -import java.util.function.Supplier; /** * @author hal.hildebrand */ public class GenesisContext extends ViewContext { - public GenesisContext(Context context, Supplier diadem, Parameters params, Signer signer, - BlockProducer blockProducer) { - super(context, diadem, params, signer, Collections.emptyMap(), blockProducer); + public GenesisContext(Context context, Parameters params, Signer signer, BlockProducer blockProducer) { + super(context, params, signer, Collections.emptyMap(), blockProducer); } @Override diff --git a/choam/src/main/java/com/salesforce/apollo/choam/Producer.java b/choam/src/main/java/com/salesforce/apollo/choam/Producer.java index 4f29c3217..19198d000 100644 --- a/choam/src/main/java/com/salesforce/apollo/choam/Producer.java +++ b/choam/src/main/java/com/salesforce/apollo/choam/Producer.java @@ -20,7 +20,6 @@ import com.salesforce.apollo.choam.support.HashedCertifiedBlock; import com.salesforce.apollo.choam.support.TxDataSource; import com.salesforce.apollo.cryptography.Digest; -import com.salesforce.apollo.cryptography.HexBloom; import com.salesforce.apollo.ethereal.Config; import com.salesforce.apollo.ethereal.Config.Builder; import com.salesforce.apollo.ethereal.Ethereal; @@ -110,8 +109,8 @@ public Producer(ViewContext view, HashedBlock lastBlock, HashedBlock checkpoint, log.debug("Roster for: {} is: {} on: {}", getViewId(), view.roster(), params().member().getId()); } - public void assembled(HexBloom diadem) { - transitions.assembled(diadem); + public void assembled() { + transitions.assembled(); } public Digest getNextViewId() { @@ -244,12 +243,14 @@ private void produceAssemble() { final var vlb = previousBlock.get(); nextViewId = vlb.hash; nextAssembly.addAll(Committee.viewMembersOf(nextViewId, params().context())); + var diadem = view.diadem(); + log.debug("Assembling: {} diadem: {} on: {}", nextViewId, diadem.compact(), params().member().getId()); final var assemble = new HashedBlock(params().digestAlgorithm(), view.produce(vlb.height().add(1), vlb.hash, Assemble.newBuilder() .setNextView( vlb.hash.toDigeste()) - .setDiadem(view.diadem() - .toHexBloome()) + .setDiadem( + diadem.toIdentityHexBloome()) .build(), checkpoint.get())); previousBlock.set(assemble); @@ -258,8 +259,9 @@ private void produceAssemble() { pending.put(assemble.hash, p); p.witnesses.put(params().member(), validation); ds.offer(validation); - log.debug("View assembly: {} block: {} height: {} body: {} from: {} on: {}", nextViewId, assemble.hash, - assemble.height(), assemble.block.getBodyCase(), getViewId(), params().member().getId()); + log.debug("View assembly: {} diadem: {} block: {} height: {} body: {} from: {} on: {}", nextViewId, diadem, + assemble.hash, assemble.height(), assemble.block.getBodyCase(), getViewId(), + params().member().getId()); } private void publish(PendingBlock p) { @@ -370,15 +372,15 @@ public void produceAssemble() { } @Override - public void reconfigure(HexBloom diadem) { - log.debug("Starting view reconfiguration: {} diadem: {} on: {}", nextViewId, diadem.compact(), + public void reconfigure() { + log.debug("Starting view reconfiguration: {} diadem: {} on: {}", nextViewId, view.diadem().compact(), params().member().getId()); assembly.set(new ViewAssembly(nextViewId, view, Producer.this::addReassemble, comms) { @Override public void complete() { super.complete(); log.debug("View reconfiguration: {} diadem: {} gathered: {} complete on: {}", nextViewId, - diadem.compact(), getSlate().size(), params().member().getId()); + view.diadem().compact(), getSlate().size(), params().member().getId()); assembled.set(true); Producer.this.transitions.viewComplete(); } 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 83fac081b..9bb91c43c 100644 --- a/choam/src/main/java/com/salesforce/apollo/choam/ViewContext.java +++ b/choam/src/main/java/com/salesforce/apollo/choam/ViewContext.java @@ -19,7 +19,6 @@ import java.util.HashMap; import java.util.Map; -import java.util.function.Supplier; import static com.salesforce.apollo.cryptography.QualifiedBase64.publicKey; @@ -35,17 +34,15 @@ public class ViewContext { private final Map roster; private final Signer signer; private final Map validators; - private final Supplier diadem; - public ViewContext(Context context, Supplier diadem, Parameters params, Signer signer, - Map validators, BlockProducer blockProducer) { + public ViewContext(Context context, Parameters params, Signer signer, Map validators, + BlockProducer blockProducer) { this.blockProducer = blockProducer; this.context = context; this.roster = new HashMap<>(); this.params = params; this.signer = signer; this.validators = validators; - this.diadem = diadem; var remapped = CHOAM.rosterMap(params.context(), context.allMembers().toList()); short pid = 0; @@ -78,7 +75,7 @@ public Context context() { } public HexBloom diadem() { - return diadem.get(); + return blockProducer.diadem(); } public Validate generateValidation(HashedBlock block) { diff --git a/choam/src/main/java/com/salesforce/apollo/choam/fsm/Driven.java b/choam/src/main/java/com/salesforce/apollo/choam/fsm/Driven.java index 60bac80db..3e0ec9ce6 100644 --- a/choam/src/main/java/com/salesforce/apollo/choam/fsm/Driven.java +++ b/choam/src/main/java/com/salesforce/apollo/choam/fsm/Driven.java @@ -9,7 +9,6 @@ import com.chiralbehaviors.tron.Entry; import com.chiralbehaviors.tron.FsmExecutor; import com.google.protobuf.ByteString; -import com.salesforce.apollo.cryptography.HexBloom; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -38,14 +37,14 @@ public interface Driven { void produceAssemble(); - void reconfigure(HexBloom diadem); + void reconfigure(); void startProduction(); enum Earner implements Driven.Transitions { AWAIT_VIEW { @Override - public Transitions assembled(HexBloom diadem) { + public Transitions assembled() { context().assembled(); return null; } @@ -94,7 +93,7 @@ public Transitions start() { } }, PROTOCOL_FAILURE { @Override - public Transitions assembled(HexBloom diadem) { + public Transitions assembled() { return null; } @@ -130,8 +129,8 @@ public void terminate() { } }, SPICE { @Override - public Transitions assembled(HexBloom diadem) { - context().reconfigure(diadem); + public Transitions assembled() { + context().reconfigure(); return null; } @@ -164,7 +163,7 @@ public Transitions viewComplete() { interface Transitions extends FsmExecutor { Logger log = LoggerFactory.getLogger(Transitions.class); - default Transitions assembled(HexBloom diadem) { + default Transitions assembled() { return null; } diff --git a/choam/src/main/java/com/salesforce/apollo/choam/support/Bootstrapper.java b/choam/src/main/java/com/salesforce/apollo/choam/support/Bootstrapper.java index d43b06e32..d7a70d594 100644 --- a/choam/src/main/java/com/salesforce/apollo/choam/support/Bootstrapper.java +++ b/choam/src/main/java/com/salesforce/apollo/choam/support/Bootstrapper.java @@ -140,7 +140,8 @@ private void checkpointCompletion(int threshold, Initial mostRecent) { if (!cps.validate(diadem, Digest.from(checkpoint.block.getHeader().getLastCheckpointHash()))) { throw new IllegalStateException("Cannot validate checkpoint: " + checkpoint.height()); } - log.info("Restored checkpoint: {} diadem: {} on: {}", checkpoint.height(), diadem, params.member().getId()); + log.info("Restored checkpoint: {} diadem: {} on: {}", checkpoint.height(), diadem.compact(), + params.member().getId()); checkpointState = cps; }); // reconstruct chain to genesis diff --git a/choam/src/test/java/com/salesforce/apollo/choam/GenesisAssemblyTest.java b/choam/src/test/java/com/salesforce/apollo/choam/GenesisAssemblyTest.java index 15e5ead2d..65c1c990e 100644 --- a/choam/src/test/java/com/salesforce/apollo/choam/GenesisAssemblyTest.java +++ b/choam/src/test/java/com/salesforce/apollo/choam/GenesisAssemblyTest.java @@ -137,6 +137,11 @@ public Block checkpoint() { return null; } + @Override + public HexBloom diadem() { + return new HexBloom(); + } + @Override public Block genesis(Map joining, Digest nextViewId, HashedBlock previous) { return CHOAM.genesis(viewId, new HexBloom(), joining, previous, committee, previous, built, @@ -165,7 +170,7 @@ public Block reconfigure(Map joining, Digest nextViewId, HashedBlo } }; HexBloom diadem = new HexBloom(); - var view = new GenesisContext(committee, () -> diadem, built, sm, reconfigure); + var view = new GenesisContext(committee, built, sm, reconfigure); KeyPair keyPair = params.getViewSigAlgorithm().generateKeyPair(); final PubKey consensus = bs(keyPair.getPublic()); 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 1ec56d90d..2350f783e 100644 --- a/choam/src/test/java/com/salesforce/apollo/choam/ViewAssemblyTest.java +++ b/choam/src/test/java/com/salesforce/apollo/choam/ViewAssemblyTest.java @@ -160,11 +160,11 @@ public ViewMember answer(InvocationOnMock invocation) throws Throwable { e -> new Verifier.DefaultVerifier( e.getValue().getPublic()))); Map views = new HashMap<>(); - HexBloom diadem = new HexBloom(DigestAlgorithm.DEFAULT.getLast(), 0); + HexBloom diadem = new HexBloom(DigestAlgorithm.DEFAULT.getLast()); context.active().forEach(m -> { SigningMember sm = (SigningMember) m; Router router = communications.get(m); - ViewContext view = new ViewContext(context, () -> diadem, params.build( + ViewContext view = new ViewContext(context, params.build( RuntimeParameters.newBuilder().setContext(context).setMember(sm).setCommunications(router).build()), new Signer.SignerImpl(consensusPairs.get(m).getPrivate(), ULong.MIN), validators, null); 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 2db6a95bd..22501db87 100644 --- a/cryptography/src/main/java/com/salesforce/apollo/cryptography/HexBloom.java +++ b/cryptography/src/main/java/com/salesforce/apollo/cryptography/HexBloom.java @@ -36,7 +36,7 @@ public class HexBloom { private final BloomFilter membership; public HexBloom(Digest initial, int count) { - assert count >= 0; + assert count > 0; var hashes = hashes(count); crowns = new Digest[count]; cardinality = 0; @@ -74,7 +74,11 @@ public HexBloom(int cardinality, List crowns, BloomFilter member } public HexBloom() { - this(DigestAlgorithm.DEFAULT.getLast(), 0); + this(DigestAlgorithm.DEFAULT.getLast(), 1); + } + + public HexBloom(Digest initial) { + this(initial, 1); } /** @@ -286,6 +290,9 @@ public static List> hashWraps(int crowns) { } public Digest compact() { + if (crowns.length == 1) { + return crowns[0]; + } return Arrays.asList(crowns).stream().reduce(crowns[0].getAlgorithm().getOrigin(), (a, b) -> a.xor(b)); }