From 78bc10a3f83e7d06cadf3f0573bc1bba6e36f526 Mon Sep 17 00:00:00 2001 From: Robin Bryce Date: Tue, 2 Jan 2024 14:20:26 +0000 Subject: [PATCH 1/2] Support hashing with idtimestamp committed AB#8859 --- simplehash/schemav2.go | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/simplehash/schemav2.go b/simplehash/schemav2.go index 8551193..e6e2184 100644 --- a/simplehash/schemav2.go +++ b/simplehash/schemav2.go @@ -4,6 +4,7 @@ package simplehash import ( "crypto/sha256" + "encoding/binary" "encoding/json" "errors" "fmt" @@ -38,10 +39,20 @@ type HashOptions struct { asConfirmed bool prefix []byte committed *timestamppb.Timestamp + idcommitted []byte } type HashOption func(*HashOptions) +// WithIDCommitted includes the snowflakeid unique commitment timestamp in the hash +// idcommitted is never (legitimately) zero +func WithIDCommitted(idcommitted uint64) HashOption { + return func(o *HashOptions) { + o.idcommitted = make([]byte, 8) + binary.BigEndian.PutUint64(o.idcommitted, idcommitted) + } +} + // WithPrefix pre-pends the provided bytes to the hash. This option can be used // multiple times and the successive bytes are appended to the prefix. This is // typically used to provide hash domain seperation where second pre-image @@ -142,6 +153,11 @@ func (h *HasherV2) HashEvent(event *v2assets.EventResponse, opts ...HashOption) return err } + // If the idcommitted is provided, add it to the hash first + if o.idcommitted != nil { + h.hasher.Write(o.idcommitted) + } + return V2HashEvent(h.hasher, v2Event) } @@ -187,6 +203,12 @@ func (h *HasherV2) HashEventJSON(event []byte, opts ...HashOption) error { // correct one. v2Event.ConfirmationStatus = v2assets.ConfirmationStatus_name[int32(v2assets.ConfirmationStatus_CONFIRMED)] } + + // If the idcommitted is provided, add it to the hash first + if o.idcommitted != nil { + h.hasher.Write(o.idcommitted) + } + return V2HashEvent(h.hasher, v2Event) } From c60c50bd3cddd239c193da9030cbee8d1b5009d7 Mon Sep 17 00:00:00 2001 From: Robin Bryce Date: Tue, 2 Jan 2024 14:36:13 +0000 Subject: [PATCH 2/2] Move the options to their own implementation file The options for controling the hasher are not part of the api event schema. Putting them in their own file makes it clear their use is the responsibility of the caller rather than formally part of the event schema. --- simplehash/options.go | 64 ++++++++++++++++++++++++++++++++++++++++++ simplehash/schemav2.go | 56 ------------------------------------ 2 files changed, 64 insertions(+), 56 deletions(-) create mode 100644 simplehash/options.go diff --git a/simplehash/options.go b/simplehash/options.go new file mode 100644 index 0000000..18d3deb --- /dev/null +++ b/simplehash/options.go @@ -0,0 +1,64 @@ +package simplehash + +import ( + "encoding/binary" + + "google.golang.org/protobuf/types/known/timestamppb" +) + +// These options are not part of the event schema. The can be used to adjust how +// the schema is applied to produce a hash for different purposes. + +type HashOptions struct { + accumulateHash bool + publicFromPermissioned bool + asConfirmed bool + prefix []byte + committed *timestamppb.Timestamp + idcommitted []byte +} + +type HashOption func(*HashOptions) + +// WithIDCommitted includes the snowflakeid unique commitment timestamp in the hash +// idcommitted is never (legitimately) zero +func WithIDCommitted(idcommitted uint64) HashOption { + return func(o *HashOptions) { + o.idcommitted = make([]byte, 8) + binary.BigEndian.PutUint64(o.idcommitted, idcommitted) + } +} + +// WithPrefix pre-pends the provided bytes to the hash. This option can be used +// multiple times and the successive bytes are appended to the prefix. This is +// typically used to provide hash domain seperation where second pre-image +// collisions are a concerne. +func WithPrefix(b []byte) HashOption { + return func(o *HashOptions) { + o.prefix = append(o.prefix, b...) + } +} + +func WithTimestampCommitted(committed *timestamppb.Timestamp) HashOption { + return func(o *HashOptions) { + o.committed = committed + } +} + +func WithAccumulate() HashOption { + return func(o *HashOptions) { + o.accumulateHash = true + } +} + +func WithPublicFromPermissioned() HashOption { + return func(o *HashOptions) { + o.publicFromPermissioned = true + } +} + +func WithAsConfirmed() HashOption { + return func(o *HashOptions) { + o.asConfirmed = true + } +} diff --git a/simplehash/schemav2.go b/simplehash/schemav2.go index e6e2184..4e142bd 100644 --- a/simplehash/schemav2.go +++ b/simplehash/schemav2.go @@ -4,7 +4,6 @@ package simplehash import ( "crypto/sha256" - "encoding/binary" "encoding/json" "errors" "fmt" @@ -13,7 +12,6 @@ import ( v2assets "github.com/datatrails/go-datatrails-common-api-gen/assets/v2/assets" "github.com/datatrails/go-datatrails-common-api-gen/marshalers/simpleoneof" "github.com/zeebo/bencode" - "google.golang.org/protobuf/types/known/timestamppb" ) var ( @@ -33,60 +31,6 @@ func NewHasherV2() HasherV2 { return h } -type HashOptions struct { - accumulateHash bool - publicFromPermissioned bool - asConfirmed bool - prefix []byte - committed *timestamppb.Timestamp - idcommitted []byte -} - -type HashOption func(*HashOptions) - -// WithIDCommitted includes the snowflakeid unique commitment timestamp in the hash -// idcommitted is never (legitimately) zero -func WithIDCommitted(idcommitted uint64) HashOption { - return func(o *HashOptions) { - o.idcommitted = make([]byte, 8) - binary.BigEndian.PutUint64(o.idcommitted, idcommitted) - } -} - -// WithPrefix pre-pends the provided bytes to the hash. This option can be used -// multiple times and the successive bytes are appended to the prefix. This is -// typically used to provide hash domain seperation where second pre-image -// collisions are a concerne. -func WithPrefix(b []byte) HashOption { - return func(o *HashOptions) { - o.prefix = append(o.prefix, b...) - } -} - -func WithTimestampCommitted(committed *timestamppb.Timestamp) HashOption { - return func(o *HashOptions) { - o.committed = committed - } -} - -func WithAccumulate() HashOption { - return func(o *HashOptions) { - o.accumulateHash = true - } -} - -func WithPublicFromPermissioned() HashOption { - return func(o *HashOptions) { - o.publicFromPermissioned = true - } -} - -func WithAsConfirmed() HashOption { - return func(o *HashOptions) { - o.asConfirmed = true - } -} - // Reset resets the hasher state // This is only useful in combination with WithAccumulate func (h *HasherV2) Reset() { h.hasher.Reset() }