/** * Verifies a single signature. * @param delta the payload that we're verifying the signature on. * @param signature the signature on the payload * @param domain the authority (domain name) that should have signed the * payload. * @throws SignatureException if the signature doesn't verify. */ private void verifySingleSignature(ByteStringMessage<ProtocolWaveletDelta> delta, ProtocolSignature signature, String domain) throws SignatureException, UnknownSignerException { verifier.verify(delta.getByteString().toByteArray(), signature, domain); }
/** * Parses a {@link ByteStringMessage} from its {@link ByteString} * representation. * * @param prototype used to create a {@link Message.Builder} to parse the * message * @param byteString representation of the message * @throws InvalidProtocolBufferException if {@code byteString} is not a * valid protocol buffer */ public static <K extends Message> ByteStringMessage<K> parseFrom(K prototype, ByteString byteString) throws InvalidProtocolBufferException { return new ByteStringMessage<K>(parse(prototype, byteString), byteString); }
@Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } WaveletDeltaRecord other = (WaveletDeltaRecord) obj; if (applied == null) { if (other.applied != null) { return false; } } else if (!applied.equals(other.applied)) { return false; } if (transformed == null) { if (other.transformed != null) { return false; } } else if (!transformed.equals(other.transformed)) { return false; } return true; } }
/** * Calculates the hashed version after an applied delta is applied. */ public static HashedVersion calculateResultingHashedVersion( ByteStringMessage<ProtocolAppliedWaveletDelta> appliedDelta) throws InvalidProtocolBufferException { return HASH_FACTORY.create( appliedDelta.getByteArray(), getHashedVersionAppliedAt(appliedDelta), appliedDelta.getMessage().getOperationsApplied()); }
@Override public ProtocolSignedDelta signDelta(ByteStringMessage<ProtocolWaveletDelta> delta) { // TODO: support extended address paths. For now, there will be exactly // one signature, and we don't support federated groups. Preconditions.checkState(delta.getMessage().getAddressPathCount() == 0); ProtocolSignedDelta.Builder signedDelta = ProtocolSignedDelta.newBuilder(); signedDelta.setDelta(delta.getByteString()); signedDelta.addAllSignature(waveSigner.sign(delta)); return signedDelta.build(); }
/** * Build an applied delta message from a POJO delta. The delta is not signed. */ public static ByteStringMessage<ProtocolAppliedWaveletDelta> buildAppliedDelta(WaveletDelta delta, long applicationTimestamp) { ProtocolWaveletDelta protoDelta = CoreWaveletOperationSerializer.serialize(delta); ByteStringMessage<ProtocolWaveletDelta> deltaBytes = ByteStringMessage.serializeMessage(protoDelta); ProtocolSignedDelta signedDelta = ProtocolSignedDelta.newBuilder().setDelta(deltaBytes.getByteString()).build(); return AppliedDeltaUtil.buildAppliedDelta(signedDelta, delta.getTargetVersion(), delta.size(), applicationTimestamp); }
@Override public void submitRequest(WaveletName waveletName, ProtocolWaveletDelta delta, final SubmitRequestListener listener) { Preconditions.checkState(initialized, "Wave server not yet initialized"); if (delta.getOperationCount() == 0) { listener.onFailure("Empty delta at version " + delta.getHashedVersion().getVersion()); return; } // The serialised version of this delta happens now. This should be the only place, ever! ProtocolSignedDelta signedDelta = certificateManager.signDelta(ByteStringMessage.serializeMessage(delta)); submitDelta(waveletName, delta, signedDelta, new SubmitResultListener() { @Override public void onFailure(FederationError errorMessage) { listener.onFailure(errorMessage.getErrorMessage()); } @Override public void onSuccess(int operationsApplied, ProtocolHashedVersion hashedVersionAfterApplication, long applicationTimestamp) { listener.onSuccess(operationsApplied, CoreWaveletOperationSerializer.deserialize(hashedVersionAfterApplication), applicationTimestamp); } }); }
@Override public ByteStringMessage<ProtocolWaveletDelta> verifyDelta(ProtocolSignedDelta signedDelta) throws SignatureException, UnknownSignerException { ByteStringMessage<ProtocolWaveletDelta> delta; try { delta = ByteStringMessage.parseProtocolWaveletDelta(signedDelta.getDelta()); } catch (InvalidProtocolBufferException e) { throw new IllegalArgumentException("signed delta does not contain valid delta", e); } if (disableVerfication) { return delta; } List<String> domains = getParticipantDomains(delta.getMessage()); if (domains.size() != signedDelta.getSignatureCount()) { throw new SignatureException("found " + domains.size() + " domains in " + "extended address path, but " + signedDelta.getSignatureCount() + " signatures."); } for (int i = 0; i < domains.size(); i++) { String domain = domains.get(i); ProtocolSignature signature = signedDelta.getSignature(i); verifySingleSignature(delta, signature, domain); } return delta; }
for (ByteString delta : deltas) { try { appliedDeltas.add(ByteStringMessage.parseProtocolAppliedWaveletDelta(delta)); } catch (InvalidProtocolBufferException e) { LOG.info("Invalid applied delta protobuf for incoming " + getWaveletName(), e); ProtocolSignedDelta toVerify = appliedDelta.getMessage().getSignedOriginalDelta(); HashedVersion deltaEndVersion; try {
/** * Parses a {@link ProtocolAppliedWaveletDelta}. Convenience method, equivalent to * {@code from(ProtocolAppliedWaveletDelta.getDefaultInstanceForType(), byteString)}. */ public static ByteStringMessage<ProtocolAppliedWaveletDelta> parseProtocolAppliedWaveletDelta( ByteString byteString) throws InvalidProtocolBufferException { return new ByteStringMessage<ProtocolAppliedWaveletDelta>( ProtocolAppliedWaveletDelta.parseFrom(byteString), byteString); }
@Override public boolean isDeltaSigner(HashedVersion version, ByteString signerId) { ByteStringMessage<ProtocolAppliedWaveletDelta> appliedDelta = lookupAppliedDeltaByEndVersion(version); if (appliedDelta == null) { return false; } ProtocolSignedDelta signedDelta = appliedDelta.getMessage().getSignedOriginalDelta(); for (ProtocolSignature signature : signedDelta.getSignatureList()) { if (signature.getSignerId().equals(signerId)) return true; } return false; } }
/** * Read the applied delta at the current file position. After method call, * file position is directly after applied delta field. */ private ByteStringMessage<ProtocolAppliedWaveletDelta> readAppliedDelta(int length) throws IOException { if (length == 0) { return null; } byte[] bytes = new byte[length]; file.readFully(bytes); try { return ByteStringMessage.parseProtocolAppliedWaveletDelta(ByteString.copyFrom(bytes)); } catch (InvalidProtocolBufferException e) { throw new IOException(e); } }
/** * Write an applied delta to the current position in the file. Returns number of bytes written. */ private int writeAppliedDelta(ByteStringMessage<ProtocolAppliedWaveletDelta> delta) throws IOException { if (delta != null) { byte[] bytes = delta.getByteArray(); file.write(bytes); return bytes.length; } else { return 0; } }
@Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((applied == null) ? 0 : applied.hashCode()); result = prime * result + ((transformed == null) ? 0 : transformed.hashCode()); return result; }
/** * Build an applied delta message from a POJO delta. The delta is not signed. */ public static ByteStringMessage<ProtocolAppliedWaveletDelta> buildAppliedDelta(WaveletDelta delta, long applicationTimestamp) { ProtocolWaveletDelta protoDelta = CoreWaveletOperationSerializer.serialize(delta); ByteStringMessage<ProtocolWaveletDelta> deltaBytes = ByteStringMessage.serializeMessage(protoDelta); ProtocolSignedDelta signedDelta = ProtocolSignedDelta.newBuilder().setDelta(deltaBytes.getByteString()).build(); return AppliedDeltaUtil.buildAppliedDelta(signedDelta, delta.getTargetVersion(), delta.size(), applicationTimestamp); }
/** * Creates an applied delta message from a signed protocol delta and * application metadata. * * @param signedDelta the original delta * @param appliedAtVersion version at which the delta applied * @param operationsApplied number of ops in the delta * @param applicationTimestamp timestamp of application */ public static ByteStringMessage<ProtocolAppliedWaveletDelta> buildAppliedDelta( ProtocolSignedDelta signedDelta, HashedVersion appliedAtVersion, int operationsApplied, long applicationTimestamp) { ProtocolAppliedWaveletDelta.Builder appliedDeltaBuilder = ProtocolAppliedWaveletDelta .newBuilder() .setSignedOriginalDelta(signedDelta) .setOperationsApplied(operationsApplied) .setApplicationTimestamp(applicationTimestamp); // TODO(soren): Only set hashedVersionAppliedAt when different from the // signed delta's target version if we rev the protocol. appliedDeltaBuilder.setHashedVersionAppliedAt( CoreWaveletOperationSerializer.serialize(appliedAtVersion)); return ByteStringMessage.serializeMessage(appliedDeltaBuilder.build()); }
ByteStringMessage.parseProtocolWaveletDelta( appliedDelta.getMessage().getSignedOriginalDelta().getDelta()); WaveletDelta delta = CoreWaveletOperationSerializer.deserialize(protocolDelta.getMessage()); if (appliedDelta.getMessage().hasHashedVersionAppliedAt()) { LOG.warning("Hashes are the same but applied delta has hashed_version_applied_at");
/** * Builds a transformed delta from an applied delta and its transformed ops. */ public static TransformedWaveletDelta buildTransformedDelta( ByteStringMessage<ProtocolAppliedWaveletDelta> appliedDeltaBytes, WaveletDelta transformed) throws InvalidProtocolBufferException { ProtocolAppliedWaveletDelta appliedDelta = appliedDeltaBytes.getMessage(); Preconditions.checkArgument( getHashedVersionAppliedAt(appliedDeltaBytes).equals(transformed.getTargetVersion())); Preconditions.checkArgument(appliedDelta.getOperationsApplied() == transformed.size()); HashedVersion resultingVersion = HASH_FACTORY.create(appliedDeltaBytes.getByteArray(), transformed.getTargetVersion(), appliedDelta.getOperationsApplied()); return TransformedWaveletDelta.cloneOperations(resultingVersion, appliedDelta.getApplicationTimestamp(), transformed); }
/** * Parses a {@link ProtocolWaveletDelta}. Convenience method, equivalent to * {@code from(ProtocolWaveletDelta.getDefaultInstanceForType(), byteString)}. */ public static ByteStringMessage<ProtocolWaveletDelta> parseProtocolWaveletDelta( ByteString byteString) throws InvalidProtocolBufferException { return new ByteStringMessage<ProtocolWaveletDelta>( ProtocolWaveletDelta.parseFrom(byteString), byteString); }
/** * Inspects the given applied delta to determine the {@code HashedVersion} it * was applied at. * This may require looking at the contained {@code ProtocolWaveletDelta}. * * @param appliedDeltaBytes to inspect * @return hashed version the delta was applied at * @throws InvalidProtocolBufferException if the contained * {@code ProtocolWaveletDelta} is invalid * (is only inspected if the applied delta has the hashed version set) */ public static HashedVersion getHashedVersionAppliedAt( ByteStringMessage<ProtocolAppliedWaveletDelta> appliedDeltaBytes) throws InvalidProtocolBufferException { ProtocolAppliedWaveletDelta appliedDelta = appliedDeltaBytes.getMessage(); return CoreWaveletOperationSerializer.deserialize( // If the delta was transformed, the version it was actually applied at is specified // in the top-level message, otherwise we take if from the original signed delta. appliedDelta.hasHashedVersionAppliedAt() ? appliedDelta.getHashedVersionAppliedAt() : ProtocolWaveletDelta.parseFrom(appliedDelta.getSignedOriginalDelta().getDelta()) .getHashedVersion()); }