From cf96f514f4ee2dfc6b615dc0ca28a74c0374fc5d Mon Sep 17 00:00:00 2001 From: Stefan Boberg Date: Mon, 6 Sep 2021 19:01:16 +0200 Subject: Change Compact Binary Package API to represent binary attachments as compressed buffers identified by their raw hash. Change Compact Binary Package serialization for binary attachments to compressed buffers and objects as objects followed by their hash. Ported changes from Zousar's pending CL17372417 --- zencore/compactbinaryvalidation.cpp | 143 ++++++++++++++++++++++-------------- 1 file changed, 86 insertions(+), 57 deletions(-) (limited to 'zencore/compactbinaryvalidation.cpp') diff --git a/zencore/compactbinaryvalidation.cpp b/zencore/compactbinaryvalidation.cpp index 52f625313..316da76a6 100644 --- a/zencore/compactbinaryvalidation.cpp +++ b/zencore/compactbinaryvalidation.cpp @@ -416,92 +416,125 @@ ValidateCbPackageField(MemoryView& View, CbValidateMode Mode, CbValidateError& E static IoHash ValidateCbPackageAttachment(CbFieldView& Value, MemoryView& View, CbValidateMode Mode, CbValidateError& Error) { - const CbObjectView ObjectView = Value.AsObjectView(); - if (Value.HasError()) + if (const CbObjectView ObjectView = Value.AsObjectView(); !Value.HasError()) { - const MemoryView BinaryView = Value.AsBinaryView(); - if (Value.HasError() && EnumHasAnyFlags(Mode, CbValidateMode::Package)) + return CbObject().GetHash(); + } + + if (const IoHash ObjectAttachmentHash = Value.AsObjectAttachment(); !Value.HasError()) + { + if (CbFieldView ObjectField = ValidateCbPackageField(View, Mode, Error)) { - if (EnumHasAnyFlags(Mode, CbValidateMode::Package)) + const CbObjectView InnerObjectView = ObjectField.AsObjectView(); + if (EnumHasAnyFlags(Mode, CbValidateMode::Package) && ObjectField.HasError()) { AddError(Error, CbValidateError::InvalidPackageFormat); } + else if (EnumHasAnyFlags(Mode, CbValidateMode::PackageHash) && (ObjectAttachmentHash != InnerObjectView.GetHash())) + { + AddError(Error, CbValidateError::InvalidPackageHash); + } + return ObjectAttachmentHash; } - else if (BinaryView.GetSize()) + } + else if (const IoHash BinaryAttachmentHash = Value.AsBinaryAttachment(); !Value.HasError()) + { + if (CbFieldView BinaryField = ValidateCbPackageField(View, Mode, Error)) { - if (EnumHasAnyFlags(Mode, CbValidateMode::Package | CbValidateMode::PackageHash)) + const MemoryView BinaryView = BinaryField.AsBinaryView(); + if (EnumHasAnyFlags(Mode, CbValidateMode::Package) && BinaryField.HasError()) { - CompressedBuffer Buffer = CompressedBuffer::FromCompressed(SharedBuffer::MakeView(BinaryView)); - if (EnumHasAnyFlags(Mode, CbValidateMode::Package) && Buffer.IsNull()) + AddError(Error, CbValidateError::InvalidPackageFormat); + } + else + { + if (EnumHasAnyFlags(Mode, CbValidateMode::Package) && BinaryView.IsEmpty()) { - AddError(Error, CbValidateError::InvalidPackageFormat); + AddError(Error, CbValidateError::NullPackageAttachment); } - if (EnumHasAnyFlags(Mode, CbValidateMode::PackageHash) && - (IoHash::FromBLAKE3(Buffer.GetRawHash()) != IoHash::HashBuffer(Buffer.DecompressToComposite()))) + if (EnumHasAnyFlags(Mode, CbValidateMode::PackageHash) && (BinaryAttachmentHash != IoHash::HashBuffer(BinaryView))) { AddError(Error, CbValidateError::InvalidPackageHash); } - return IoHash::FromBLAKE3(Buffer.GetRawHash()); } + return BinaryAttachmentHash; } } - else + else if (const MemoryView BinaryView = Value.AsBinaryView(); !Value.HasError()) { - if (ObjectView) + if (BinaryView.GetSize() > 0) { - if (CbFieldView HashField = ValidateCbPackageField(View, Mode, Error)) + CompressedBuffer Buffer = CompressedBuffer::FromCompressed(SharedBuffer::MakeView(BinaryView)); + if (EnumHasAnyFlags(Mode, CbValidateMode::Package) && Buffer.IsNull()) { - const IoHash Hash = HashField.AsAttachment(); - if (EnumHasAnyFlags(Mode, CbValidateMode::Package) && HashField.HasError()) - { - AddError(Error, CbValidateError::InvalidPackageFormat); - } - if (EnumHasAnyFlags(Mode, CbValidateMode::PackageHash) && (Hash != ObjectView.GetHash())) - { - AddError(Error, CbValidateError::InvalidPackageHash); - } - return Hash; + AddError(Error, CbValidateError::NullPackageAttachment); } + if (EnumHasAnyFlags(Mode, CbValidateMode::PackageHash) && + (IoHash::FromBLAKE3(Buffer.GetRawHash()) != IoHash::HashBuffer(Buffer.DecompressToComposite()))) + { + AddError(Error, CbValidateError::InvalidPackageHash); + } + return IoHash::FromBLAKE3(Buffer.GetRawHash()); } else { - return CbObject().GetHash(); + if (EnumHasAnyFlags(Mode, CbValidateMode::Package)) + { + AddError(Error, CbValidateError::NullPackageAttachment); + } + return IoHash::HashBuffer(MemoryView()); } } - return {}; -} - -static IoHash -ValidateCbPackageObject(CbFieldView& Value, MemoryView& View, CbValidateMode Mode, CbValidateError& Error) -{ - CbObjectView Object = Value.AsObjectView(); - if (Value.HasError()) + else { if (EnumHasAnyFlags(Mode, CbValidateMode::Package)) { AddError(Error, CbValidateError::InvalidPackageFormat); } } - else if (CbFieldView HashField = ValidateCbPackageField(View, Mode, Error)) + + return IoHash(); +} + +static IoHash +ValidateCbPackageObject(CbFieldView& Value, MemoryView& View, CbValidateMode Mode, CbValidateError& Error) +{ + if (IoHash RootObjectHash = Value.AsHash(); !Value.HasError() && !Value.IsAttachment()) { - const IoHash Hash = HashField.AsAttachment(); + CbFieldView RootObjectField = ValidateCbPackageField(View, Mode, Error); + if (EnumHasAnyFlags(Mode, CbValidateMode::Package)) { - if (!Object) - { - AddError(Error, CbValidateError::NullPackageObject); - } - if (HashField.HasError()) + if (RootObjectField.HasError()) { AddError(Error, CbValidateError::InvalidPackageFormat); } - else if (Hash != Value.GetHash()) + } + + const CbObjectView RootObjectView = RootObjectField.AsObjectView(); + if (EnumHasAnyFlags(Mode, CbValidateMode::Package)) + { + if (!RootObjectView) { - AddError(Error, CbValidateError::InvalidPackageHash); + AddError(Error, CbValidateError::NullPackageObject); } } - return Hash; + + if (EnumHasAnyFlags(Mode, CbValidateMode::PackageHash) && (RootObjectHash != RootObjectView.GetHash())) + { + AddError(Error, CbValidateError::InvalidPackageHash); + } + + return RootObjectHash; + } + else + { + if (EnumHasAnyFlags(Mode, CbValidateMode::Package)) + { + AddError(Error, CbValidateError::InvalidPackageFormat); + } } + return IoHash(); } @@ -562,24 +595,20 @@ ValidateCompactBinaryPackage(MemoryView View, CbValidateMode Mode) uint32_t ObjectCount = 0; while (CbFieldView Value = ValidateCbPackageField(View, Mode, Error)) { - if (Value.IsBinary()) + if (Value.IsHash() && !Value.IsAttachment()) { - const IoHash Hash = ValidateCbPackageAttachment(Value, View, Mode, Error); - if (EnumHasAnyFlags(Mode, CbValidateMode::Package)) + ValidateCbPackageObject(Value, View, Mode, Error); + if (++ObjectCount > 1 && EnumHasAnyFlags(Mode, CbValidateMode::Package)) { - Attachments.push_back(Hash); - if (Value.AsBinaryView().IsEmpty()) - { - AddError(Error, CbValidateError::NullPackageAttachment); - } + AddError(Error, CbValidateError::MultiplePackageObjects); } } - else if (Value.IsObject()) + else if (Value.IsBinary() || Value.IsAttachment() || Value.IsObject()) { - ValidateCbPackageObject(Value, View, Mode, Error); - if (++ObjectCount > 1 && EnumHasAnyFlags(Mode, CbValidateMode::Package)) + const IoHash Hash = ValidateCbPackageAttachment(Value, View, Mode, Error); + if (EnumHasAnyFlags(Mode, CbValidateMode::Package)) { - AddError(Error, CbValidateError::MultiplePackageObjects); + Attachments.push_back(Hash); } } else if (Value.IsNull()) -- cgit v1.2.3