test(pki): align revocation fixtures with store authority
Rebuild revocation test credentials through the target staged-content store and real credential persistence path. Preserve strict foreign-store rejection while restoring full coverage of revocation transitions, corruption handling, concurrency, and durability semantics.
This commit is contained in:
@@ -64,8 +64,6 @@ import org.junit.jupiter.api.TestFactory;
|
|||||||
import org.junit.jupiter.api.io.TempDir;
|
import org.junit.jupiter.api.io.TempDir;
|
||||||
|
|
||||||
import zeroecho.core.io.Util;
|
import zeroecho.core.io.Util;
|
||||||
import zeroecho.pki.api.EncodedObject;
|
|
||||||
import zeroecho.pki.api.Encoding;
|
|
||||||
import zeroecho.pki.api.FormatId;
|
import zeroecho.pki.api.FormatId;
|
||||||
import zeroecho.pki.api.IssuerRef;
|
import zeroecho.pki.api.IssuerRef;
|
||||||
import zeroecho.pki.api.PkiException;
|
import zeroecho.pki.api.PkiException;
|
||||||
@@ -109,9 +107,11 @@ final class FilesystemRevocationJournalTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void legalTransitionsAreContiguousDurableAndPermanentIsTerminal() throws Exception {
|
void legalTransitionsAreContiguousDurableAndPermanentIsTerminal() throws Exception {
|
||||||
|
System.out.println("legalTransitionsAreContiguousDurableAndPermanentIsTerminal");
|
||||||
Path root = temporaryDirectory.resolve("legal");
|
Path root = temporaryDirectory.resolve("legal");
|
||||||
Credential credential = credential("legal");
|
Credential credential;
|
||||||
try (FilesystemPkiStore store = store(root)) {
|
try (FilesystemPkiStore store = store(root)) {
|
||||||
|
credential = credential(store, "legal");
|
||||||
store.putCredential(credential);
|
store.putCredential(credential);
|
||||||
assertTransition(store, hold(credential), 1L, RevocationState.HELD);
|
assertTransition(store, hold(credential), 1L, RevocationState.HELD);
|
||||||
assertTransition(store, unhold(credential), 2L, RevocationState.CLEAR);
|
assertTransition(store, unhold(credential), 2L, RevocationState.CLEAR);
|
||||||
@@ -128,14 +128,16 @@ final class FilesystemRevocationJournalTest {
|
|||||||
assertEquals(RevocationState.PERMANENTLY_REVOKED, journal.latest().state());
|
assertEquals(RevocationState.PERMANENTLY_REVOKED, journal.latest().state());
|
||||||
assertEquals(RevocationReason.KEY_COMPROMISE, journal.latest().permanentReason().orElseThrow());
|
assertEquals(RevocationReason.KEY_COMPROMISE, journal.latest().permanentReason().orElseThrow());
|
||||||
}
|
}
|
||||||
|
System.out.println("legalTransitionsAreContiguousDurableAndPermanentIsTerminal...ok");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void everyLegalPermanentTransitionIsAccepted() throws Exception {
|
void everyLegalPermanentTransitionIsAccepted() throws Exception {
|
||||||
|
System.out.println("everyLegalPermanentTransitionIsAccepted");
|
||||||
try (FilesystemPkiStore store = store(temporaryDirectory.resolve("legal-permanent"))) {
|
try (FilesystemPkiStore store = store(temporaryDirectory.resolve("legal-permanent"))) {
|
||||||
Credential direct = credential("permanent-from-none");
|
Credential direct = credential(store, "permanent-from-none");
|
||||||
Credential fromClear = credential("permanent-from-clear");
|
Credential fromClear = credential(store, "permanent-from-clear");
|
||||||
Credential fromHeld = credential("permanent-from-held");
|
Credential fromHeld = credential(store, "permanent-from-held");
|
||||||
store.putCredential(direct);
|
store.putCredential(direct);
|
||||||
store.putCredential(fromClear);
|
store.putCredential(fromClear);
|
||||||
store.putCredential(fromHeld);
|
store.putCredential(fromHeld);
|
||||||
@@ -156,15 +158,17 @@ final class FilesystemRevocationJournalTest {
|
|||||||
assertEquals(List.of(RevocationState.HELD, RevocationState.PERMANENTLY_REVOKED), states(heldJournal));
|
assertEquals(List.of(RevocationState.HELD, RevocationState.PERMANENTLY_REVOKED), states(heldJournal));
|
||||||
assertEquals(2L, heldJournal.latest().revision());
|
assertEquals(2L, heldJournal.latest().revision());
|
||||||
}
|
}
|
||||||
|
System.out.println("everyLegalPermanentTransitionIsAccepted...ok");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void illegalAndInvalidCommandsFailBeforeJournalMutation() throws Exception {
|
void illegalAndInvalidCommandsFailBeforeJournalMutation() throws Exception {
|
||||||
|
System.out.println("illegalAndInvalidCommandsFailBeforeJournalMutation");
|
||||||
try (FilesystemPkiStore store = store(temporaryDirectory.resolve("illegal"))) {
|
try (FilesystemPkiStore store = store(temporaryDirectory.resolve("illegal"))) {
|
||||||
Credential unknown = credential("unknown");
|
Credential unknown = credential(store, "unknown");
|
||||||
assertCode("REVOCATION_CREDENTIAL_NOT_FOUND", () -> transition(store, hold(unknown)));
|
assertCode("REVOCATION_CREDENTIAL_NOT_FOUND", () -> transition(store, hold(unknown)));
|
||||||
|
|
||||||
Credential credential = credential("known");
|
Credential credential = credential(store, "known");
|
||||||
store.putCredential(credential);
|
store.putCredential(credential);
|
||||||
assertCode("REVOCATION_TRANSITION_ILLEGAL", () -> transition(store, unhold(credential)));
|
assertCode("REVOCATION_TRANSITION_ILLEGAL", () -> transition(store, unhold(credential)));
|
||||||
assertThrows(IllegalArgumentException.class, () -> revoke(credential, RevocationReason.CERTIFICATE_HOLD));
|
assertThrows(IllegalArgumentException.class, () -> revoke(credential, RevocationReason.CERTIFICATE_HOLD));
|
||||||
@@ -190,17 +194,19 @@ final class FilesystemRevocationJournalTest {
|
|||||||
() -> transition(store, revoke(credential, RevocationReason.CA_COMPROMISE)));
|
() -> transition(store, revoke(credential, RevocationReason.CA_COMPROMISE)));
|
||||||
assertArrayEquals(permanentBytes, FsOperations.readAll(journalPath));
|
assertArrayEquals(permanentBytes, FsOperations.readAll(journalPath));
|
||||||
|
|
||||||
Credential invalidRemove = credential("invalid-remove");
|
Credential invalidRemove = credential(store, "invalid-remove");
|
||||||
store.putCredential(invalidRemove);
|
store.putCredential(invalidRemove);
|
||||||
assertThrows(IllegalArgumentException.class, () -> revoke(invalidRemove, RevocationReason.REMOVE_FROM_CRL));
|
assertThrows(IllegalArgumentException.class, () -> revoke(invalidRemove, RevocationReason.REMOVE_FROM_CRL));
|
||||||
assertTrue(store.getRevocationJournal(invalidRemove.credentialId()).isEmpty());
|
assertTrue(store.getRevocationJournal(invalidRemove.credentialId()).isEmpty());
|
||||||
}
|
}
|
||||||
|
System.out.println("illegalAndInvalidCommandsFailBeforeJournalMutation...ok");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void sameCredentialConcurrentHoldHasExactlyOneCommittedWinner() throws Exception {
|
void sameCredentialConcurrentHoldHasExactlyOneCommittedWinner() throws Exception {
|
||||||
|
System.out.println("sameCredentialConcurrentHoldHasExactlyOneCommittedWinner");
|
||||||
try (FilesystemPkiStore store = store(temporaryDirectory.resolve("concurrent"))) {
|
try (FilesystemPkiStore store = store(temporaryDirectory.resolve("concurrent"))) {
|
||||||
Credential credential = credential("concurrent");
|
Credential credential = credential(store, "concurrent");
|
||||||
store.putCredential(credential);
|
store.putCredential(credential);
|
||||||
CyclicBarrier barrier = new CyclicBarrier(2);
|
CyclicBarrier barrier = new CyclicBarrier(2);
|
||||||
ExecutorService executor = Executors.newFixedThreadPool(2);
|
ExecutorService executor = Executors.newFixedThreadPool(2);
|
||||||
@@ -215,21 +221,23 @@ final class FilesystemRevocationJournalTest {
|
|||||||
assertEquals(1, journal.transitions().size());
|
assertEquals(1, journal.transitions().size());
|
||||||
assertEquals(1L, journal.latest().revision());
|
assertEquals(1L, journal.latest().revision());
|
||||||
}
|
}
|
||||||
|
System.out.println("sameCredentialConcurrentHoldHasExactlyOneCommittedWinner...ok");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void conflictingTransitionsSerializeWithoutLostUpdates() throws Exception {
|
void conflictingTransitionsSerializeWithoutLostUpdates() throws Exception {
|
||||||
|
System.out.println("conflictingTransitionsSerializeWithoutLostUpdates");
|
||||||
try (FilesystemPkiStore store = store(temporaryDirectory.resolve("concurrent-conflicts"))) {
|
try (FilesystemPkiStore store = store(temporaryDirectory.resolve("concurrent-conflicts"))) {
|
||||||
ExecutorService executor = Executors.newFixedThreadPool(2);
|
ExecutorService executor = Executors.newFixedThreadPool(2);
|
||||||
try {
|
try {
|
||||||
Credential fromNone = credential("hold-vs-permanent");
|
Credential fromNone = credential(store, "hold-vs-permanent");
|
||||||
store.putCredential(fromNone);
|
store.putCredential(fromNone);
|
||||||
runConcurrent(store, hold(fromNone), revoke(fromNone, RevocationReason.KEY_COMPROMISE), executor);
|
runConcurrent(store, hold(fromNone), revoke(fromNone, RevocationReason.KEY_COMPROMISE), executor);
|
||||||
RevocationJournal fromNoneJournal = store.getRevocationJournal(fromNone.credentialId()).orElseThrow();
|
RevocationJournal fromNoneJournal = store.getRevocationJournal(fromNone.credentialId()).orElseThrow();
|
||||||
assertEquals(RevocationState.PERMANENTLY_REVOKED, fromNoneJournal.latest().state());
|
assertEquals(RevocationState.PERMANENTLY_REVOKED, fromNoneJournal.latest().state());
|
||||||
assertTrue(fromNoneJournal.transitions().size() == 1 || fromNoneJournal.transitions().size() == 2);
|
assertTrue(fromNoneJournal.transitions().size() == 1 || fromNoneJournal.transitions().size() == 2);
|
||||||
|
|
||||||
Credential fromHeld = credential("unhold-vs-permanent");
|
Credential fromHeld = credential(store, "unhold-vs-permanent");
|
||||||
store.putCredential(fromHeld);
|
store.putCredential(fromHeld);
|
||||||
transition(store, hold(fromHeld));
|
transition(store, hold(fromHeld));
|
||||||
runConcurrent(store, unhold(fromHeld), revoke(fromHeld, RevocationReason.CA_COMPROMISE), executor);
|
runConcurrent(store, unhold(fromHeld), revoke(fromHeld, RevocationReason.CA_COMPROMISE), executor);
|
||||||
@@ -237,7 +245,7 @@ final class FilesystemRevocationJournalTest {
|
|||||||
assertEquals(RevocationState.PERMANENTLY_REVOKED, fromHeldJournal.latest().state());
|
assertEquals(RevocationState.PERMANENTLY_REVOKED, fromHeldJournal.latest().state());
|
||||||
assertTrue(fromHeldJournal.transitions().size() == 2 || fromHeldJournal.transitions().size() == 3);
|
assertTrue(fromHeldJournal.transitions().size() == 2 || fromHeldJournal.transitions().size() == 3);
|
||||||
|
|
||||||
Credential reasons = credential("competing-permanent-reasons");
|
Credential reasons = credential(store, "competing-permanent-reasons");
|
||||||
store.putCredential(reasons);
|
store.putCredential(reasons);
|
||||||
List<Boolean> results = runConcurrent(store, revoke(reasons, RevocationReason.KEY_COMPROMISE),
|
List<Boolean> results = runConcurrent(store, revoke(reasons, RevocationReason.KEY_COMPROMISE),
|
||||||
revoke(reasons, RevocationReason.CA_COMPROMISE), executor);
|
revoke(reasons, RevocationReason.CA_COMPROMISE), executor);
|
||||||
@@ -251,13 +259,15 @@ final class FilesystemRevocationJournalTest {
|
|||||||
executor.shutdownNow();
|
executor.shutdownNow();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
System.out.println("conflictingTransitionsSerializeWithoutLostUpdates...ok");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void unrelatedCredentialTransitionProgressesWhileAnotherCredentialLockIsHeld() throws Exception {
|
void unrelatedCredentialTransitionProgressesWhileAnotherCredentialLockIsHeld() throws Exception {
|
||||||
|
System.out.println("unrelatedCredentialTransitionProgressesWhileAnotherCredentialLockIsHeld");
|
||||||
try (FilesystemPkiStore store = store(temporaryDirectory.resolve("independent-locks"))) {
|
try (FilesystemPkiStore store = store(temporaryDirectory.resolve("independent-locks"))) {
|
||||||
Credential blocked = credential("blocked");
|
Credential blocked = credential(store, "blocked");
|
||||||
Credential independent = credential("independent");
|
Credential independent = credential(store, "independent");
|
||||||
store.putCredential(blocked);
|
store.putCredential(blocked);
|
||||||
store.putCredential(independent);
|
store.putCredential(independent);
|
||||||
|
|
||||||
@@ -289,13 +299,15 @@ final class FilesystemRevocationJournalTest {
|
|||||||
executor.shutdownNow();
|
executor.shutdownNow();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
System.out.println("unrelatedCredentialTransitionProgressesWhileAnotherCredentialLockIsHeld...ok");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void copiedNamespaceJournalAndRegressingTransitionTimeFailClosed() throws Exception {
|
void copiedNamespaceJournalAndRegressingTransitionTimeFailClosed() throws Exception {
|
||||||
|
System.out.println("copiedNamespaceJournalAndRegressingTransitionTimeFailClosed");
|
||||||
Path root = temporaryDirectory.resolve("corrupt");
|
Path root = temporaryDirectory.resolve("corrupt");
|
||||||
Credential credential = credential("corrupt");
|
|
||||||
try (FilesystemPkiStore store = store(root)) {
|
try (FilesystemPkiStore store = store(root)) {
|
||||||
|
Credential credential = credential(store, "corrupt");
|
||||||
store.putCredential(credential);
|
store.putCredential(credential);
|
||||||
transition(store, hold(credential));
|
transition(store, hold(credential));
|
||||||
assertCode("REVOCATION_TRANSITION_CONFLICT",
|
assertCode("REVOCATION_TRANSITION_CONFLICT",
|
||||||
@@ -308,6 +320,7 @@ final class FilesystemRevocationJournalTest {
|
|||||||
FsCodec.encode(FsCodec.REVOCATION_JOURNAL, invalid));
|
FsCodec.encode(FsCodec.REVOCATION_JOURNAL, invalid));
|
||||||
assertCode("REVOCATION_STATE_CORRUPT", () -> store.getRevocationJournal(credential.credentialId()));
|
assertCode("REVOCATION_STATE_CORRUPT", () -> store.getRevocationJournal(credential.credentialId()));
|
||||||
}
|
}
|
||||||
|
System.out.println("copiedNamespaceJournalAndRegressingTransitionTimeFailClosed...ok");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -356,9 +369,11 @@ final class FilesystemRevocationJournalTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void obsoleteCurrentAndHistoryLayoutCannotInfluenceTrustedJournalOrResolver() throws Exception {
|
void obsoleteCurrentAndHistoryLayoutCannotInfluenceTrustedJournalOrResolver() throws Exception {
|
||||||
|
System.out.println("obsoleteCurrentAndHistoryLayoutCannotInfluenceTrustedJournalOrResolver");
|
||||||
Path root = temporaryDirectory.resolve("obsolete-layout");
|
Path root = temporaryDirectory.resolve("obsolete-layout");
|
||||||
Credential credential = credential("obsolete-layout");
|
Credential credential;
|
||||||
try (FilesystemPkiStore store = store(root)) {
|
try (FilesystemPkiStore store = store(root)) {
|
||||||
|
credential = credential(store, "obsolete-layout");
|
||||||
store.putCredential(credential);
|
store.putCredential(credential);
|
||||||
}
|
}
|
||||||
Path legacyDirectory = new FsPaths(root).revocationDir(credential.credentialId());
|
Path legacyDirectory = new FsPaths(root).revocationDir(credential.credentialId());
|
||||||
@@ -378,12 +393,14 @@ final class FilesystemRevocationJournalTest {
|
|||||||
assertEquals(RevocationState.HELD,
|
assertEquals(RevocationState.HELD,
|
||||||
reopened.getRevocationJournal(credential.credentialId()).orElseThrow().latest().state());
|
reopened.getRevocationJournal(credential.credentialId()).orElseThrow().latest().state());
|
||||||
}
|
}
|
||||||
|
System.out.println("obsoleteCurrentAndHistoryLayoutCannotInfluenceTrustedJournalOrResolver...ok");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void durabilityUncertaintyMakesEveryStoreOperationFailClosed() throws Exception {
|
void durabilityUncertaintyMakesEveryStoreOperationFailClosed() throws Exception {
|
||||||
|
System.out.println("durabilityUncertaintyMakesEveryStoreOperationFailClosed");
|
||||||
try (FilesystemPkiStore store = store(temporaryDirectory.resolve("uncertain"))) {
|
try (FilesystemPkiStore store = store(temporaryDirectory.resolve("uncertain"))) {
|
||||||
Credential credential = credential("uncertain");
|
Credential credential = credential(store, "uncertain");
|
||||||
store.putCredential(credential);
|
store.putCredential(credential);
|
||||||
Field field = FilesystemPkiStore.class.getDeclaredField("durabilityUncertain");
|
Field field = FilesystemPkiStore.class.getDeclaredField("durabilityUncertain");
|
||||||
field.setAccessible(true);
|
field.setAccessible(true);
|
||||||
@@ -393,6 +410,7 @@ final class FilesystemRevocationJournalTest {
|
|||||||
assertCode("STORE_DURABILITY_UNCONFIRMED", store::listCas);
|
assertCode("STORE_DURABILITY_UNCONFIRMED", store::listCas);
|
||||||
assertCode("STORE_DURABILITY_UNCONFIRMED", store::signingNow);
|
assertCode("STORE_DURABILITY_UNCONFIRMED", store::signingNow);
|
||||||
}
|
}
|
||||||
|
System.out.println("durabilityUncertaintyMakesEveryStoreOperationFailClosed...ok");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static CompletableFuture<Boolean> attemptHold(FilesystemPkiStore store, Credential credential,
|
private static CompletableFuture<Boolean> attemptHold(FilesystemPkiStore store, Credential credential,
|
||||||
@@ -437,12 +455,15 @@ final class FilesystemRevocationJournalTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void assertPersistedCorruptionRejected(CorruptionCase corruption) throws Exception {
|
private void assertPersistedCorruptionRejected(CorruptionCase corruption) throws Exception {
|
||||||
|
System.out.println("strictCodecCorruptionFailsReadAndTransitionWithoutOverwrite[" + corruption.description
|
||||||
|
+ "]");
|
||||||
String suffix = "corrupt-" + corruption.name().toLowerCase(java.util.Locale.ROOT);
|
String suffix = "corrupt-" + corruption.name().toLowerCase(java.util.Locale.ROOT);
|
||||||
Path root = temporaryDirectory.resolve(suffix);
|
Path root = temporaryDirectory.resolve(suffix);
|
||||||
Credential credential = credential(suffix);
|
Credential credential;
|
||||||
Path journalPath;
|
Path journalPath;
|
||||||
byte[] corrupt;
|
byte[] corrupt;
|
||||||
try (FilesystemPkiStore store = store(root)) {
|
try (FilesystemPkiStore store = store(root)) {
|
||||||
|
credential = credential(store, suffix);
|
||||||
store.putCredential(credential);
|
store.putCredential(credential);
|
||||||
journalPath = new FsPaths(root).revocationJournal(credential.credentialId());
|
journalPath = new FsPaths(root).revocationJournal(credential.credentialId());
|
||||||
corrupt = corruption.bytes(credential.credentialId());
|
corrupt = corruption.bytes(credential.credentialId());
|
||||||
@@ -455,6 +476,7 @@ final class FilesystemRevocationJournalTest {
|
|||||||
assertCode("REVOCATION_STATE_CORRUPT", () -> transition(reopened, hold(credential)));
|
assertCode("REVOCATION_STATE_CORRUPT", () -> transition(reopened, hold(credential)));
|
||||||
assertArrayEquals(before, FsOperations.readAll(journalPath));
|
assertArrayEquals(before, FsOperations.readAll(journalPath));
|
||||||
}
|
}
|
||||||
|
System.out.println("strictCodecCorruptionFailsReadAndTransitionWithoutOverwrite...ok");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static List<RevocationState> states(RevocationJournal journal) {
|
private static List<RevocationState> states(RevocationJournal journal) {
|
||||||
@@ -493,27 +515,16 @@ final class FilesystemRevocationJournalTest {
|
|||||||
return new FilesystemPkiStore(root, FsPkiStoreOptions.defaults());
|
return new FilesystemPkiStore(root, FsPkiStoreOptions.defaults());
|
||||||
}
|
}
|
||||||
|
|
||||||
private Credential credential(String suffix) {
|
private static Credential credential(FilesystemPkiStore store, String suffix) throws IOException {
|
||||||
return new Credential(new PkiId("credential:" + suffix), new FormatId("x509"),
|
return new Credential(new PkiId("credential:" + suffix), new FormatId("x509"),
|
||||||
new IssuerRef(new PkiId("ca:issuer")), new SubjectRef("CN=" + suffix),
|
new IssuerRef(new PkiId("ca:issuer")), new SubjectRef("CN=" + suffix),
|
||||||
new Validity(TIME.minusSeconds(60), TIME.plusSeconds(60)), suffix, new PkiId("key:" + suffix),
|
new Validity(TIME.minusSeconds(60), TIME.plusSeconds(60)), suffix, new PkiId("key:" + suffix),
|
||||||
new CaProfileBinding(new zeroecho.pki.api.profile.CertificateProfileRef("default", 1, new byte[32])),
|
new CaProfileBinding(new zeroecho.pki.api.profile.CertificateProfileRef("default", 1, new byte[32])),
|
||||||
CredentialStatus.ISSUED,
|
CredentialStatus.ISSUED,
|
||||||
fixtureReference(),
|
zeroecho.pki.testkit.PkiTestRuntime.stageCredential(store, new byte[] { 1, 2, 3 }),
|
||||||
new SimpleAttributeSet());
|
new SimpleAttributeSet());
|
||||||
}
|
}
|
||||||
|
|
||||||
private zeroecho.pki.api.content.DurableContentReference fixtureReference() {
|
|
||||||
try {
|
|
||||||
FilesystemStagedContentStore staged = new FilesystemStagedContentStore(
|
|
||||||
temporaryDirectory.resolve("reference-fixtures"), "0123456789abcdef0123456789abcdef");
|
|
||||||
return zeroecho.pki.testkit.PkiTestRuntime.fixtureReference(staged, Encoding.DER,
|
|
||||||
new byte[] { 1, 2, 3 });
|
|
||||||
} catch (IOException exception) {
|
|
||||||
throw new AssertionError("Unable to stage credential fixture", exception);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static byte[] journalPayload(PkiId credentialId, long journalVersion, RawTransition... transitions)
|
private static byte[] journalPayload(PkiId credentialId, long journalVersion, RawTransition... transitions)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
ByteArrayOutputStream output = envelope();
|
ByteArrayOutputStream output = envelope();
|
||||||
|
|||||||
Reference in New Issue
Block a user