Skip to content

Commit

Permalink
Merge pull request #7 from datatrails/dev/jgough/9030-event-json-hash
Browse files Browse the repository at this point in the history
Add support for eventjson to v3 simplehash hash
  • Loading branch information
honourfish authored Jan 31, 2024
2 parents 4a38691 + 7f9e645 commit bdcf623
Show file tree
Hide file tree
Showing 7 changed files with 215 additions and 17 deletions.
6 changes: 3 additions & 3 deletions simplehash/hasher.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,16 +36,16 @@ func NewEventMarshaler() *simpleoneof.Marshaler {
return v2assets.NewFlatMarshalerForEvents()
}

func (h *Hasher) applyEventOptions(o HashOptions, event *v2assets.EventResponse) {
func (h *Hasher) applyEventOptions(o HashOptions, event EventOptionApplier) {
if o.publicFromPermissioned {
PublicFromPermissionedEvent(event)
event.ToPublicIdentity()
}

// force the commited time in the hash. only useful to the service that is
// actually doing the committing. public consumers only ever see confirmed
// events with the timestamp already in place.
if o.committed != nil {
event.TimestampCommitted = o.committed
event.SetTimestampCommitted(o.committed)
}
}

Expand Down
5 changes: 5 additions & 0 deletions simplehash/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@ import (
// 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 EventOptionApplier interface {
ToPublicIdentity()
SetTimestampCommitted(*timestamppb.Timestamp)
}

type HashOptions struct {
accumulateHash bool
publicFromPermissioned bool
Expand Down
10 changes: 0 additions & 10 deletions simplehash/publicevent.go

This file was deleted.

17 changes: 15 additions & 2 deletions simplehash/schemav2.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@ import (
"encoding/json"
"fmt"
"hash"
"time"

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"
)

// V2Event is a struct that contains ONLY the event fields we want to hash for schema v2
Expand All @@ -30,6 +32,17 @@ type V2Event struct {
TenantIdentity string `json:"tenant_identity"`
}

// ToPublicIdentity converts the identity of the event into a public identity
func (e *V2Event) ToPublicIdentity() {
e.AssetIdentity = v2assets.PublicIdentityFromPermissioned(e.AssetIdentity)
e.Identity = v2assets.PublicIdentityFromPermissioned(e.Identity)
}

// SetTimestampCommitted sets the timestamp committed to the given timestamp
func (e *V2Event) SetTimestampCommitted(timestamp *timestamppb.Timestamp) {
e.TimestampCommitted = timestamp.AsTime().Format(time.RFC3339Nano)
}

type HasherV2 struct {
Hasher
}
Expand Down Expand Up @@ -64,15 +77,15 @@ func (h *HasherV2) HashEvent(event *v2assets.EventResponse, opts ...HashOption)
opt(&o)
}

h.Hasher.applyEventOptions(o, event)

// Note that we _don't_ take any notice of confirmation status.

v2Event, err := V2FromEventResponse(h.marshaler, event)
if err != nil {
return err
}

h.Hasher.applyEventOptions(o, &v2Event)

// Hash data accumulation starts here
h.Hasher.applyHashingOptions(o)

Expand Down
75 changes: 75 additions & 0 deletions simplehash/schemav2_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@ import (
"encoding/hex"
"hash"
"testing"
"time"

v2assets "github.com/datatrails/go-datatrails-common-api-gen/assets/v2/assets"
"github.com/datatrails/go-datatrails-common-api-gen/attribute/v2/attribute"
"github.com/datatrails/go-datatrails-common-api-gen/marshalers/simpleoneof"
"github.com/golang/protobuf/ptypes/timestamp"
"google.golang.org/protobuf/types/known/timestamppb"
"gotest.tools/v3/assert"
)

Expand Down Expand Up @@ -114,6 +116,41 @@ var (
}
)

// TestV2Event_SetTimestampCommitted tests:
//
// 1. setting the timestamp gives the correctly formatted timestamp in the v2event
func TestV2Event_SetTimestampCommitted(t *testing.T) {
type args struct {
timestamp *timestamppb.Timestamp
}
tests := []struct {
name string
originalTimestamp string
args args
expected string
}{
{
name: "positive",
originalTimestamp: "2023-02-23T10:11:08.761Z",
args: args{
timestamp: timestamppb.New(time.Unix(1706700559, 43000000)),
},
expected: "2024-01-31T11:29:19.043Z",
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
e := &V2Event{
TimestampCommitted: test.originalTimestamp,
}

e.SetTimestampCommitted(test.args.timestamp)

assert.Equal(t, test.expected, e.TimestampCommitted)
})
}
}

func TestEventSimpleHashV2(t *testing.T) {
type args struct {
hasher hash.Hash
Expand Down Expand Up @@ -268,3 +305,41 @@ func TestHasherV2_HashEventJSON(t *testing.T) {
})
}
}

// TestV2Event_ToPublicIdentity tests:
//
// 1. that both identity and asset identity convert correctly to the public identity.
func TestV2Event_ToPublicIdentity(t *testing.T) {
type fields struct {
Identity string
AssetIdentity string
}
tests := []struct {
name string
fields fields
eIdentity string
eAssetIdentity string
}{
{
name: "positive",
fields: fields{
Identity: "assets/9ccdc19b-44a1-434c-afab-14f8eac3405c/events/e76a03d1-19a5-4f11-bcaf-383bb4f1dfd4",
AssetIdentity: "assets/9ccdc19b-44a1-434c-afab-14f8eac3405c",
},
eIdentity: "publicassets/9ccdc19b-44a1-434c-afab-14f8eac3405c/events/e76a03d1-19a5-4f11-bcaf-383bb4f1dfd4",
eAssetIdentity: "publicassets/9ccdc19b-44a1-434c-afab-14f8eac3405c",
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
e := &V2Event{
Identity: test.fields.Identity,
AssetIdentity: test.fields.AssetIdentity,
}
e.ToPublicIdentity()

assert.Equal(t, test.eIdentity, e.Identity)
assert.Equal(t, test.eAssetIdentity, e.AssetIdentity)
})
}
}
50 changes: 48 additions & 2 deletions simplehash/schemav3.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ import (
"encoding/json"
"fmt"
"hash"
"time"

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"
)

// V3Event is a struct that contains ONLY the event fields we want to hash for schema v3
Expand All @@ -25,6 +27,16 @@ type V3Event struct {
TenantIdentity string `json:"tenant_identity"`
}

// ToPublicIdentity converts the identity of the event into a public identity
func (e *V3Event) ToPublicIdentity() {
e.Identity = v2assets.PublicIdentityFromPermissioned(e.Identity)
}

// SetTimestampCommitted sets the timestamp committed to the given timestamp
func (e *V3Event) SetTimestampCommitted(timestamp *timestamppb.Timestamp) {
e.TimestampCommitted = timestamp.AsTime().Format(time.RFC3339Nano)
}

func V3HashEvent(hasher hash.Hash, v3Event V3Event) error {

var err error
Expand Down Expand Up @@ -110,13 +122,47 @@ func (h *HasherV3) HashEvent(event *v2assets.EventResponse, opts ...HashOption)
opt(&o)
}

h.applyEventOptions(o, event)

v3Event, err := V3FromEventResponse(h.marshaler, event)
if err != nil {
return err
}

h.applyEventOptions(o, &v3Event)

h.applyHashingOptions(o)

return V3HashEvent(h.hasher, v3Event)
}

// HashEventFromJson hashes a single event according to the canonical simple hash event
// format available to api consumers. The source event is in json format.
//
// Options:
// - WithIDCommitted prefix the data to hash with the bigendian encoding of
// idtimestamp before hashing.
// - WithPrefix is used to provide domain separation, the provided bytes are
// pre-pended to the data to be hashed. Eg H(prefix || data)
// This option can be used multiple times, the prefix bytes are appended to
// any previously supplied.
// - WithAccumulate callers wishing to implement batched hashing of multiple
// events in series should set this. They should call Reset() at their batch
// boundaries.
// - WithPublicFromPermissioned should be set if the event is the
// permissioned (owner) counter part of a public attestation.
func (h *HasherV3) HashEventFromJSON(eventJson []byte, opts ...HashOption) error {

o := HashOptions{}
for _, opt := range opts {
opt(&o)
}

v3Event, err := V3FromEventJSON(eventJson)
if err != nil {
return err
}

h.applyEventOptions(o, &v3Event)

h.applyHashingOptions(o)

return V3HashEvent(h.hasher, v3Event)
Expand Down
69 changes: 69 additions & 0 deletions simplehash/schemav3_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@ import (
"crypto/sha256"
"encoding/hex"
"testing"
"time"

v2assets "github.com/datatrails/go-datatrails-common-api-gen/assets/v2/assets"
"google.golang.org/protobuf/types/known/timestamppb"
"gotest.tools/v3/assert"
)

Expand Down Expand Up @@ -62,3 +64,70 @@ func TestHasherV3_HashEvent(t *testing.T) {
})
}
}

// TestV3Event_SetTimestampCommitted tests:
//
// 1. setting the timestamp gives the correctly formatted timestamp in the v3event
func TestV3Event_SetTimestampCommitted(t *testing.T) {
type args struct {
timestamp *timestamppb.Timestamp
}
tests := []struct {
name string
originalTimestamp string
args args
expected string
}{
{
name: "positive",
originalTimestamp: "2023-02-23T10:11:08.761Z",
args: args{
timestamp: timestamppb.New(time.Unix(1706700559, 43000000)),
},
expected: "2024-01-31T11:29:19.043Z",
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
e := &V3Event{
TimestampCommitted: test.originalTimestamp,
}

e.SetTimestampCommitted(test.args.timestamp)

assert.Equal(t, test.expected, e.TimestampCommitted)
})
}
}

// TestV3Event_ToPublicIdentity tests:
//
// 1. that identity convert correctly to the public identity.
func TestV3Event_ToPublicIdentity(t *testing.T) {
type fields struct {
Identity string
}
tests := []struct {
name string
fields fields
eIdentity string
}{
{
name: "positive",
fields: fields{
Identity: "assets/9ccdc19b-44a1-434c-afab-14f8eac3405c/events/e76a03d1-19a5-4f11-bcaf-383bb4f1dfd4",
},
eIdentity: "publicassets/9ccdc19b-44a1-434c-afab-14f8eac3405c/events/e76a03d1-19a5-4f11-bcaf-383bb4f1dfd4",
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
e := &V2Event{
Identity: test.fields.Identity,
}
e.ToPublicIdentity()

assert.Equal(t, test.eIdentity, e.Identity)
})
}
}

0 comments on commit bdcf623

Please sign in to comment.