From 3e8d83730a63c0b3dbb96bdae5dc963a4e4b77a9 Mon Sep 17 00:00:00 2001 From: jgough Date: Wed, 15 Jan 2025 11:43:49 +0000 Subject: [PATCH 01/10] Make log verification app agnostic and remove azblob from massifs re: AB#10216 --- logverification/app/appentry.go | 226 ++++++++++------ logverification/app/appentry_test.go | 300 +++++---------------- logverification/app/assetsv2.go | 170 ------------ logverification/app/assetsv2_test.go | 49 ---- logverification/app/eventsv1.go | 152 ----------- logverification/app/logversion0.go | 8 +- logverification/app/logversion0_test.go | 44 --- logverification/app/massifgetteroptions.go | 13 - logverification/massif.go | 13 - logverification/validation.go | 4 - logverification/validation_test.go | 27 +- logverification/verifylist.go | 2 +- 12 files changed, 219 insertions(+), 789 deletions(-) delete mode 100644 logverification/app/assetsv2.go delete mode 100644 logverification/app/assetsv2_test.go delete mode 100644 logverification/app/eventsv1.go delete mode 100644 logverification/app/logversion0_test.go diff --git a/logverification/app/appentry.go b/logverification/app/appentry.go index 7b8c419..3f1af30 100644 --- a/logverification/app/appentry.go +++ b/logverification/app/appentry.go @@ -2,12 +2,9 @@ package app import ( "crypto/sha256" - "encoding/binary" "errors" "fmt" - "github.com/datatrails/go-datatrails-common-api-gen/assets/v2/assets" - "github.com/datatrails/go-datatrails-common/logger" "github.com/datatrails/go-datatrails-merklelog/massifs" "github.com/datatrails/go-datatrails-merklelog/mmr" "github.com/google/uuid" @@ -55,14 +52,23 @@ type AppEntryGetter interface { AppID() string LogID() []byte LogTenant() (string, error) - ExtraBytes() []byte - SerializedBytes() []byte Domain() byte - + SerializedBytes() []byte MMRIndex() uint64 - IDTimestamp() string - MMRSalt() ([]byte, error) - MMREntry() ([]byte, error) + + MMRSalt(options ...MassifGetterOption) ([]byte, error) +} + +// MMREntryGetter gets an mmrEntry from the given serialized bytes and corresponding log entry +type MMREntryGetter interface { + MMREntry(options ...MassifGetterOption) ([]byte, error) +} + +// TrieEntryGetter gets the trie entry +type TrieEntryGetter interface { + ExtraBytes(options ...MassifGetterOption) ([]byte, error) + IDTimestamp(options ...MassifGetterOption) ([]byte, error) + TrieEntry(options ...MassifGetterOption) ([]byte, error) } // AppEntryMassifGetter gets the massif for a specific app entry. @@ -82,6 +88,8 @@ type AppEntryVerifier interface { // VerifiableAppEntry includes all methods that could be needed for a verifiable app entry. type VerifiableAppEntry interface { AppEntryGetter + MMREntryGetter + TrieEntryGetter AppEntryMassifGetter AppEntryVerifier } @@ -92,7 +100,7 @@ type MMREntryFields struct { // domain defines the hashing schema for the MMR Entry domain byte - // serializedBytes are app (customer) provided fields in the MMR Entry, serialized in a consistent way. + // serialized bytes is the serialized bytes that get hashed as part of the MMR Entry serializedBytes []byte } @@ -109,80 +117,39 @@ type AppEntry struct { // logID is a uuid in byte form of the specific log identifier logID []byte - // extraBytes are extrabytes provided by datatrails for the specific app - extraBytes []byte - // MMREntryFields used to determine the MMR Entry mmrEntryFields *MMREntryFields - // MerkleLogCommit used to define information about the log entry - merkleLogCommit *assets.MerkleLogCommit + // mmrIndex of the corresponding log entry + mmrIndex uint64 } // NewAppEntry creates a new app entry entry func NewAppEntry( appId string, logId []byte, - extraBytes []byte, mmrEntryFields *MMREntryFields, - merklelogCommit *assets.MerkleLogCommit, + mmrIndex uint64, ) *AppEntry { appEntry := &AppEntry{ - appID: appId, - logID: logId, - extraBytes: extraBytes, - mmrEntryFields: mmrEntryFields, - merkleLogCommit: merklelogCommit, + appID: appId, + logID: logId, + mmrEntryFields: mmrEntryFields, + mmrIndex: mmrIndex, } return appEntry } -// MMREntry derives the mmr entry of the corresponding log entry from the app data. -// -// MMREntry is: -// - H( Domain | MMR Salt | Serialized Bytes) -func (ae *AppEntry) MMREntry() ([]byte, error) { - - hasher := sha256.New() - - // domain - hasher.Write([]byte{ae.mmrEntryFields.domain}) - - // mmr salt - mmrSalt, err := ae.MMRSalt() - if err != nil { - return nil, err - } - - hasher.Write(mmrSalt) - - // serialized bytes - hasher.Write(ae.mmrEntryFields.serializedBytes) - - return hasher.Sum(nil), nil - -} - // MMRIndex gets the mmr index of the corresponding log entry. func (ae *AppEntry) MMRIndex() uint64 { - - if ae.merkleLogCommit == nil { - return 0 - } - - return ae.merkleLogCommit.Index + return ae.mmrIndex } -// IDTimestamp gets the idtimestamp of the corresponding log entry. -func (ae *AppEntry) IDTimestamp() string { - - if ae.merkleLogCommit == nil { - return "" - } - - return ae.merkleLogCommit.Idtimestamp +// SerializedBytes gets the serialized bytes used to generate id of the corresponding mmr entry. +func (ae *AppEntry) SerializedBytes() []byte { + return ae.mmrEntryFields.serializedBytes } // AppID gets the app id of the corresponding log entry. @@ -208,14 +175,43 @@ func (ae *AppEntry) LogTenant() (string, error) { } +// TrieEntry gets the corresponding log trie entry for the app entry. +func (ae *AppEntry) TrieEntry(options ...MassifGetterOption) ([]byte, error) { + + massifContext, err := ae.Massif(options...) + if err != nil { + return nil, err + } + + trieEntry, err := massifContext.GetTrieEntry(ae.MMRIndex()) + if err != nil { + return nil, err + } + + return trieEntry, nil + +} + // ExtraBytes gets the extrabytes of the corresponding log entry. -func (ae *AppEntry) ExtraBytes() []byte { - return ae.extraBytes +func (ae *AppEntry) ExtraBytes(options ...MassifGetterOption) ([]byte, error) { + + trieEntry, err := ae.TrieEntry(options...) + if err != nil { + return nil, err + } + + return massifs.GetExtraBytes(trieEntry, 0, 0), nil } -// SerializedBytes gets the serialized bytes used to derive the mmr entry. -func (ae *AppEntry) SerializedBytes() []byte { - return ae.mmrEntryFields.serializedBytes +// IDTimestamp gets the idtimestamp of the corresponding log entry. +func (ae *AppEntry) IDTimestamp(options ...MassifGetterOption) ([]byte, error) { + + trieEntry, err := ae.TrieEntry(options...) + if err != nil { + return nil, err + } + + return massifs.GetIdtimestamp(trieEntry, 0, 0), nil } // Domain gets the domain byte used to derive the mmr entry. @@ -227,32 +223,97 @@ func (ae *AppEntry) Domain() byte { // MMRSalt is the datatrails provided fields included on the MMR Entry. // // this is (extrabytes | idtimestamp) for any apps that adhere to log entry version 1. -func (ae *AppEntry) MMRSalt() ([]byte, error) { +func (ae *AppEntry) MMRSalt(options ...MassifGetterOption) ([]byte, error) { mmrSalt := make([]byte, MMRSaltSize) - copy(mmrSalt[:ExtraBytesSize], ae.extraBytes) + extraBytes, err := ae.ExtraBytes(options...) + if err != nil { + return nil, err + } - // get the byte representation of idtimestamp - idTimestamp, _, err := massifs.SplitIDTimestampHex(ae.merkleLogCommit.Idtimestamp) + idTimestamp, err := ae.IDTimestamp(options...) if err != nil { return nil, err } - idTimestampBytes := make([]byte, IDTimestapSizeBytes) - binary.BigEndian.PutUint64(idTimestampBytes, idTimestamp) + copy(mmrSalt[:ExtraBytesSize], extraBytes) - copy(mmrSalt[ExtraBytesSize:], idTimestampBytes) + copy(mmrSalt[ExtraBytesSize:], idTimestamp) return mmrSalt, nil } +// MMREntry derives the mmr entry of the corresponding log entry from the app data. +// +// MMREntry is: +// - H( Domain | MMR Salt | Serialized Bytes) +// +// The MMR Salt is sourced from the corresponding log entry +func (ae *AppEntry) MMREntry(options ...MassifGetterOption) ([]byte, error) { + + logVersion0 := true + + // first find the log version + massifContext, err := ae.Massif(options...) + if err != nil { + return nil, err + } + + extraBytes, err := ae.ExtraBytes(WithMassifContext(massifContext)) + if err != nil { + return nil, err + } + + // the only implementation of log version 0 is assetsv2 + // so check for the assetsv2 app domain (0). + if extraBytes[0] != 0 { + logVersion0 = false + } + + if logVersion0 { + hasher := LogVersion0Hasher{} + + idTimestamp, err := ae.IDTimestamp(WithMassifContext(massifContext)) + if err != nil { + return nil, err + } + + eventHash, err := hasher.HashEvent(ae.mmrEntryFields.serializedBytes, idTimestamp) + if err != nil { + return nil, err + } + + return eventHash, nil + } + + // if we get here we know its a log version 1 entry + + hasher := sha256.New() + + // domain + hasher.Write([]byte{ae.mmrEntryFields.domain}) + + // mmr salt + mmrSalt, err := ae.MMRSalt() + if err != nil { + return nil, err + } + + hasher.Write(mmrSalt) + + // serialized bytes + hasher.Write(ae.mmrEntryFields.serializedBytes) + + return hasher.Sum(nil), nil + +} + /** Massif gets the massif context, for the massif of the corresponding log entry from the app data. * * The following massif options can be used, in priority order: * - WithMassifContext * - WithMassifReader - * - WithAzblobReader * * Example WithMassifReader: * @@ -271,20 +332,13 @@ func (ae *AppEntry) Massif(options ...MassifGetterOption) (*massifs.MassifContex return massifOptions.massifContext, nil } - var massifReader MassifGetter // now check if we have a massif reader - if massifOptions.massifGetter != nil { - massifReader = massifOptions.massifGetter - } else { - // otherwise use azblob reader to get it - if massifOptions.azblobReader == nil { - return nil, errors.New("no way of determining massif of app entry, please provide either a massif context, massif reader or azblob reader") - } + if massifOptions.massifGetter == nil { + return nil, errors.New("no way of determining massif of app entry, please provide either a massif context or massif getter") - newMassifReader := massifs.NewMassifReader(logger.Sugar, massifOptions.azblobReader) - massifReader = &newMassifReader } + massifReader := massifOptions.massifGetter massifHeight := massifOptions.MassifHeight logIdentity := massifOptions.TenantId @@ -300,7 +354,7 @@ func (ae *AppEntry) Massif(options ...MassifGetterOption) (*massifs.MassifContex logIdentity = fmt.Sprintf("tenant/%s", logUuid.String()) } - return Massif(ae.merkleLogCommit.Index, massifReader, logIdentity, massifHeight) + return Massif(ae.mmrIndex, massifReader, logIdentity, massifHeight) } diff --git a/logverification/app/appentry_test.go b/logverification/app/appentry_test.go index 908c5a3..712f224 100644 --- a/logverification/app/appentry_test.go +++ b/logverification/app/appentry_test.go @@ -1,22 +1,75 @@ package app import ( + "crypto/sha256" + "fmt" "testing" - "github.com/datatrails/go-datatrails-common-api-gen/assets/v2/assets" + "github.com/datatrails/go-datatrails-merklelog/massifs" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) +// testMassifContext generates a massif context with 2 entries +// +// the first entry is a known log version 0 entry +// the seconds entry is a known log version 1 entry +func testMassifContext(t *testing.T) *massifs.MassifContext { + + start := massifs.MassifStart{ + MassifHeight: 3, + } + + testMassifContext := &massifs.MassifContext{ + Start: start, + LogBlobContext: massifs.LogBlobContext{ + BlobPath: "test", + Tags: map[string]string{}, + }, + } + + data, err := start.MarshalBinary() + require.NoError(t, err) + + testMassifContext.Data = append(data, testMassifContext.InitIndexData()...) + + testMassifContext.Tags["firstindex"] = fmt.Sprintf("%016x", testMassifContext.Start.FirstIndex) + + hasher := sha256.New() + + idtimestampStr := "0x01931acb7b14043b00" + + // convert idtimestamp from bytes to uint64 + idTimestamp, _, err := massifs.SplitIDTimestampHex(idtimestampStr) + require.NoError(t, err) + + extraBytes := []byte{1, // app domain + 1, 2, 3, 4, 5, 6, 7, 8, + 1, 2, 3, 4, 5, 6, 7, 8, + 1, 2, 3, 4, 5, 6, 7} // 23 remaining bytes + + mmrEntry := []byte{ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, // 32 byte hash + } + + _, err = testMassifContext.AddHashedLeaf(hasher, idTimestamp, extraBytes, []byte("test"), []byte("events/1234"), mmrEntry) + require.NoError(t, err) + + return testMassifContext +} + // TestNewAppEntry tests: // // 1. we can get all non derived fields for the app entry getter func TestNewAppEntry(t *testing.T) { type args struct { - appId string - logId []byte - extraBytes []byte - mmrEntryFields *MMREntryFields - merklelogCommit *assets.MerkleLogCommit + appId string + logId []byte + mmrEntryFields *MMREntryFields + mmrIndex uint64 } tests := []struct { name string @@ -28,36 +81,20 @@ func TestNewAppEntry(t *testing.T) { args: args{ appId: "events/1234", logId: []byte("1234"), - extraBytes: []byte{ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - }, // 24 bytes long mmrEntryFields: &MMREntryFields{ domain: 0, serializedBytes: []byte("its a me, an app entry"), }, - merklelogCommit: &assets.MerkleLogCommit{ - Index: 16, - Idtimestamp: "0x1234", - }, + mmrIndex: 16, }, expected: &AppEntry{ appID: "events/1234", logID: []byte("1234"), - extraBytes: []byte{ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - }, // 24 bytes long mmrEntryFields: &MMREntryFields{ domain: 0, serializedBytes: []byte("its a me, an app entry"), }, - merkleLogCommit: &assets.MerkleLogCommit{ - Index: 16, - Idtimestamp: "0x1234", - }, + mmrIndex: 16, }, }, } @@ -66,166 +103,22 @@ func TestNewAppEntry(t *testing.T) { actual := NewAppEntry( test.args.appId, test.args.logId, - test.args.extraBytes, test.args.mmrEntryFields, - test.args.merklelogCommit, + test.args.mmrIndex, ) appEntryGetter := AppEntryGetter(actual) assert.Equal(t, test.expected.appID, appEntryGetter.AppID()) assert.Equal(t, test.expected.logID, appEntryGetter.LogID()) - assert.Equal(t, test.expected.extraBytes, appEntryGetter.ExtraBytes()) // mmr entry fields assert.Equal(t, test.expected.mmrEntryFields.domain, appEntryGetter.Domain()) assert.Equal(t, test.expected.mmrEntryFields.serializedBytes, appEntryGetter.SerializedBytes()) - // merklelog commit - assert.Equal(t, test.expected.merkleLogCommit.Index, appEntryGetter.MMRIndex()) - assert.Equal(t, test.expected.merkleLogCommit.Idtimestamp, appEntryGetter.IDTimestamp()) - - }) - } -} - -// TestAppEntry_MMREntry tests: -// -// 1. Known Answer Test (KAT) for mmr entry for log version 1 -func TestAppEntry_MMREntry(t *testing.T) { - type fields struct { - extraBytes []byte - mmrEntryFields *MMREntryFields - merkleLogCommit *assets.MerkleLogCommit - } - tests := []struct { - name string - fields fields - expected []byte - err error - }{ - // TODO: Add test cases. - } - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - - ae := &AppEntry{ - extraBytes: test.fields.extraBytes, - mmrEntryFields: test.fields.mmrEntryFields, - merkleLogCommit: test.fields.merkleLogCommit, - } - actual, err := ae.MMREntry() - - assert.Equal(t, test.err, err) - assert.Equal(t, test.expected, actual) - }) - } -} - -// TestAppEntry_MMRIndex tests: -// -// 1. an index > 0 returns that index. -// 2. an index == 0 returns 0. -// 3. a nil merklelog commit returns 0. -func TestAppEntry_MMRIndex(t *testing.T) { - type fields struct { - merkleLogCommit *assets.MerkleLogCommit - } - tests := []struct { - name string - fields fields - expected uint64 - }{ - { - name: "non 0 index", - fields: fields{ - merkleLogCommit: &assets.MerkleLogCommit{ - Index: 176, - }, - }, - expected: 176, - }, - { - name: "0 index", - fields: fields{ - merkleLogCommit: &assets.MerkleLogCommit{ - Index: 0, - }, - }, - expected: 0, - }, - { - name: "nil merklelog commit", - fields: fields{ - merkleLogCommit: nil, - }, - expected: 0, - }, - } - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - - ae := &AppEntry{ - merkleLogCommit: test.fields.merkleLogCommit, - } - - actual := ae.MMRIndex() - - assert.Equal(t, test.expected, actual) - }) - } -} - -// TestAppEntry_IDTimestamp tests: -// -// 1. a non empty idtimestamp returns that idtimestamp. -// 2. an empty idtimestamp returns "". -// 3. a nil merklelog commit returns "". -func TestAppEntry_IDTimestamp(t *testing.T) { - type fields struct { - merkleLogCommit *assets.MerkleLogCommit - } - tests := []struct { - name string - fields fields - expected string - }{ - { - name: "non empty idtimestamp", - fields: fields{ - merkleLogCommit: &assets.MerkleLogCommit{ - Idtimestamp: "0x1234", - }, - }, - expected: "0x1234", - }, - { - name: "empty idtimestamp", - fields: fields{ - merkleLogCommit: &assets.MerkleLogCommit{ - Idtimestamp: "", - }, - }, - expected: "", - }, - { - name: "nil merklelog commit", - fields: fields{ - merkleLogCommit: nil, - }, - expected: "", - }, - } - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - - ae := &AppEntry{ - merkleLogCommit: test.fields.merkleLogCommit, - } - - actual := ae.IDTimestamp() + // mmr index + assert.Equal(t, test.expected.mmrIndex, appEntryGetter.MMRIndex()) - assert.Equal(t, test.expected, actual) }) } } @@ -233,12 +126,12 @@ func TestAppEntry_IDTimestamp(t *testing.T) { // TestAppEntry_MMRSalt tests: // // 1. Known Answer Test for MMRSalt for log version 0. -// 2. Boundary overflow test for mmr salt values higher than 24 bytes -// 3. Boundary underflow test for mmr salt values lower than 24 bytes func TestAppEntry_MMRSalt(t *testing.T) { + + testMassifContext := testMassifContext(t) + type fields struct { - extraBytes []byte - merkleLogCommit *assets.MerkleLogCommit + mmrIndex uint64 } tests := []struct { name string @@ -249,15 +142,7 @@ func TestAppEntry_MMRSalt(t *testing.T) { { name: "positive kat", fields: fields{ - extraBytes: []byte{ - 1, // app domain - 1, 2, 3, 4, 5, 6, 7, 8, - 1, 2, 3, 4, 5, 6, 7, 8, - 1, 2, 3, 4, 5, 6, 7, // 23 remaining bytes - }, - merkleLogCommit: &assets.MerkleLogCommit{ - Idtimestamp: "0x01931acb7b14043b00", - }, + mmrIndex: 0, }, expected: []byte{ 0x1, // app domain @@ -267,57 +152,14 @@ func TestAppEntry_MMRSalt(t *testing.T) { 0x93, 0x1a, 0xcb, 0x7b, 0x14, 0x4, 0x3b, 0x0, // idtimestamp }, }, - { - name: "extrabyte overflow boundary", - fields: fields{ - extraBytes: []byte{ - 1, // app domain - 1, 2, 3, 4, 5, 6, 7, 8, - 1, 2, 3, 4, 5, 6, 7, 8, - 1, 2, 3, 4, 5, 6, 7, 8, // 24 remaining bytes (overflow by 1 byte) - }, - merkleLogCommit: &assets.MerkleLogCommit{ - Idtimestamp: "0x01931acb7b14043b00", - }, - }, - expected: []byte{ - 0x1, // app domain - 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, - 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, - 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, // remaining bytes - 0x93, 0x1a, 0xcb, 0x7b, 0x14, 0x4, 0x3b, 0x0, // idtimestamp - }, - }, - { - name: "extrabyte underflow boundary", - fields: fields{ - extraBytes: []byte{ - 1, // app domain - 1, 2, 3, 4, 5, 6, 7, 8, - 1, 2, 3, 4, 5, 6, 7, 8, - 1, 2, 3, 4, 5, 6, // 22 remaining bytes (undeflow by 1 byte) - }, - merkleLogCommit: &assets.MerkleLogCommit{ - Idtimestamp: "0x01931acb7b14043b00", - }, - }, - expected: []byte{ - 0x1, // app domain - 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, - 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, - 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x0, // remaining bytes (expect last byte to be padded) - 0x93, 0x1a, 0xcb, 0x7b, 0x14, 0x4, 0x3b, 0x0, // idtimestamp - }, - }, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { ae := &AppEntry{ - extraBytes: test.fields.extraBytes, - merkleLogCommit: test.fields.merkleLogCommit, + mmrIndex: test.fields.mmrIndex, } - actual, err := ae.MMRSalt() + actual, err := ae.MMRSalt(WithMassifContext(testMassifContext)) assert.Equal(t, test.err, err) assert.Equal(t, test.expected, actual) diff --git a/logverification/app/assetsv2.go b/logverification/app/assetsv2.go deleted file mode 100644 index f482a15..0000000 --- a/logverification/app/assetsv2.go +++ /dev/null @@ -1,170 +0,0 @@ -package app - -import ( - "crypto/sha256" - "encoding/json" - "sort" - "strings" - - "github.com/datatrails/go-datatrails-common-api-gen/assets/v2/assets" - "github.com/datatrails/go-datatrails-merklelog/mmr" - "github.com/google/uuid" - "google.golang.org/protobuf/encoding/protojson" -) - -/** - * assetsv2 contains all log entry specific functions for the assetsv2 app (app domain 0). - */ - -// AssetsV2AppEntry is the assetsv2 app provided data for a corresponding log entry. -type AssetsV2AppEntry struct { - *AppEntry -} - -// NewAssetsV2AppEntries takes a list of events JSON (e.g. from the assetsv2 events list API), converts them -// into AssetsV2AppEntries and then returns them sorted by ascending MMR index. -func NewAssetsV2AppEntries(eventsJson []byte) ([]VerifiableAppEntry, error) { - // get the event list out of events - eventListJson := struct { - Events []json.RawMessage `json:"events"` - }{} - - err := json.Unmarshal(eventsJson, &eventListJson) - if err != nil { - return nil, err - } - - events := []VerifiableAppEntry{} - for _, eventJson := range eventListJson.Events { - verifiableEvent, err := NewAssetsV2AppEntry(eventJson) - if err != nil { - return nil, err - } - - events = append(events, verifiableEvent) - } - - // Sorting the events by MMR index guarantees that they're sorted in log append order. - sort.Slice(events, func(i, j int) bool { - return events[i].MMRIndex() < events[j].MMRIndex() - }) - - return events, nil -} - -// NewAssetsV2AppEntry takes a single assetsv2 event JSON and returns an AssetsV2AppEntry, -// providing just enough information to verify the incluson of and identify the event. -func NewAssetsV2AppEntry(eventJson []byte) (*AssetsV2AppEntry, error) { - - // special care is needed here to deal with uint64 types. json marshal / - // un marshal treats them as strings because they don't fit in a - // javascript Number - - // Unmarshal into a generic type to get just the bits we need. Use - // defered decoding to get the raw merklelog entry as it must be - // unmarshaled using protojson and the specific generated target type. - entry := struct { - Identity string `json:"identity,omitempty"` - TenantIdentity string `json:"tenant_identity,omitempty"` - // Note: the proof_details top level field can be ignored here because it is a 'oneof' - MerklelogEntry json.RawMessage `json:"merklelog_entry,omitempty"` - }{} - err := json.Unmarshal(eventJson, &entry) - if err != nil { - return nil, err - } - - merkleLog := &assets.MerkleLogEntry{} - err = protojson.Unmarshal(entry.MerklelogEntry, merkleLog) - if err != nil { - return nil, err - } - - // get the logID from the event log tenant - logUuid := strings.TrimPrefix(entry.TenantIdentity, "tenant/") - logId, err := uuid.Parse(logUuid) - if err != nil { - return nil, err - } - - return &AssetsV2AppEntry{ - AppEntry: &AppEntry{ - appID: entry.Identity, - logID: logId[:], - mmrEntryFields: &MMREntryFields{ - domain: byte(0), - serializedBytes: eventJson, // we cheat a bit here, because the eventJson isn't really serialized - }, - merkleLogCommit: merkleLog.Commit, - }, - }, nil -} - -// MMREntry derives the mmr entry of the corresponding log entry from the assetsv2 app data. -// -// for assetsv2 this is simplehashv3 hash and the 'serializedBytes' is the original -// event json. -// -// NOTE: the original event json isn't really serializedbytes, but the LogVersion0 hasher includes -// the serialization. -func (ae *AssetsV2AppEntry) MMREntry() ([]byte, error) { - hasher := LogVersion0Hasher{} - eventHash, err := hasher.HashEvent(ae.mmrEntryFields.serializedBytes) - if err != nil { - return nil, err - } - - return eventHash, nil -} - -// MMRSalt derives the MMR Salt of the corresponding log entry from the app data. -// MMRSalt is the datatrails provided fields included on the MMR Entry. -// -// For assetsv2 events this is empty. -func (ae *AssetsV2AppEntry) MMRSalt() ([]byte, error) { - return []byte{}, nil // MMRSalt is always empty for assetsv2 events -} - -// VerifyProof verifies the given inclusion proof of the corresponding log entry for the app data. -func (ae *AssetsV2AppEntry) VerifyProof(proof [][]byte, options ...MassifGetterOption) (bool, error) { - - massif, err := ae.Massif(options...) - - if err != nil { - return false, err - } - - // Get the size of the complete tenant MMR - mmrSize := massif.RangeCount() - - hasher := sha256.New() - - mmrEntry, err := ae.MMREntry() - if err != nil { - return false, err - } - - return mmr.VerifyInclusion(massif, hasher, mmrSize, mmrEntry, - ae.MMRIndex(), proof) - -} - -// VerifyInclusion verifies the inclusion of the app entry -// against the corresponding log entry in immutable merkle log -// -// Returns true if the app entry is included on the log, otherwise false. -func (ae *AssetsV2AppEntry) VerifyInclusion(options ...MassifGetterOption) (bool, error) { - - massif, err := ae.Massif(options...) - - if err != nil { - return false, err - } - - proof, err := ae.Proof(WithMassifContext(massif)) - if err != nil { - return false, err - } - - return ae.VerifyProof(proof, WithMassifContext(massif)) -} diff --git a/logverification/app/assetsv2_test.go b/logverification/app/assetsv2_test.go deleted file mode 100644 index a40a957..0000000 --- a/logverification/app/assetsv2_test.go +++ /dev/null @@ -1,49 +0,0 @@ -//go:build integration && azurite - -package app - -import ( - "testing" - - "github.com/datatrails/go-datatrails-common-api-gen/assets/v2/assets" - "github.com/datatrails/go-datatrails-logverification/integrationsupport" - "github.com/datatrails/go-datatrails-merklelog/mmrtesting" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -// TestVerifyAssetsV2Event tests: -// -// An end to end run through of proof generation to proof verification -// -// of an event stored on an emulated azure blob storage. -func TestVerifyAssetsV2Event(t *testing.T) { - tc, g, _ := integrationsupport.NewAzuriteTestContext(t, "TestVerify") - - // use the same tenant ID for all events - tenantID := mmrtesting.DefaultGeneratorTenantIdentity - - events := integrationsupport.GenerateTenantLog(&tc, g, 1, tenantID, true, integrationsupport.TestMassifHeight) - event := events[len(events)-1] - - // convert the last event into json - marshaler := assets.NewFlatMarshalerForEvents() - eventJSON, err := marshaler.Marshal(event) - require.NoError(t, err) - - appEntry, err := NewAssetsV2AppEntry(eventJSON) - require.NoError(t, err) - - // NOTE: we would usually use azblob.NewReaderNoAuth() - // instead of tc.Storer. But the azurite emulator - // doesn't allow for public reads, unlike actual - // blob storage that does. - verified, err := appEntry.VerifyInclusion( - WithAzblobReader( - tc.Storer, - WithMassifHeight(integrationsupport.TestMassifHeight), - ), - ) - require.NoError(t, err) - assert.Equal(t, true, verified) -} diff --git a/logverification/app/eventsv1.go b/logverification/app/eventsv1.go deleted file mode 100644 index 4bad19a..0000000 --- a/logverification/app/eventsv1.go +++ /dev/null @@ -1,152 +0,0 @@ -package app - -import ( - "encoding/json" - "sort" - "strings" - - "github.com/datatrails/go-datatrails-common-api-gen/assets/v2/assets" - "github.com/google/uuid" - "google.golang.org/protobuf/encoding/protojson" - - "github.com/datatrails/go-datatrails-serialization/eventsv1" -) - -/** - * eventsv1 contains all log entry specific functions for the events1 app (app domain 1). - */ - -const ( - - // EventsV1AppDomain is the events v1 app domain - EventsV1AppDomain = byte(1) -) - -// EventsV1AppEntry is the assetsv2 app provided data for a corresponding log entry. -type EventsV1AppEntry struct { - *AppEntry -} - -// NewEventsV1AppEntries takes a list of events JSON (e.g. from the events list API), converts them -// into EventsV1AppEntries and then returns them sorted by ascending MMR index. -func NewEventsV1AppEntries(eventsJson []byte, logTenant string) ([]VerifiableAppEntry, error) { - // get the event list out of events - eventListJson := struct { - Events []json.RawMessage `json:"events"` - }{} - - err := json.Unmarshal(eventsJson, &eventListJson) - if err != nil { - return nil, err - } - - events := []VerifiableAppEntry{} - for _, eventJson := range eventListJson.Events { - verifiableEvent, err := NewEventsV1AppEntry(eventJson, logTenant) - if err != nil { - return nil, err - } - - events = append(events, verifiableEvent) - } - - // Sorting the events by MMR index guarantees that they're sorted in log append order. - sort.Slice(events, func(i, j int) bool { - return events[i].MMRIndex() < events[j].MMRIndex() - }) - - return events, nil -} - -// NewVerifiableEventsV1Events takes a single eventsv1 event JSON and returns a VerifiableEventsV1Event, -// providing just enough information to verify and identify the event. -func NewEventsV1AppEntry(eventJson []byte, logTenant string) (*EventsV1AppEntry, error) { - - // special care is needed here to deal with uint64 types. json marshal / - // un marshal treats them as strings because they don't fit in a - // javascript Number - - // Unmarshal into a generic type to get just the bits we need. Use - // defered decoding to get the raw merklelog entry as it must be - // unmarshaled using protojson and the specific generated target type. - entry := struct { - Identity string `json:"identity,omitempty"` - OriginTenant string `json:"origin_tenant,omitempty"` - - Attributes map[string]any `json:"attributes,omitempty"` - Trails []string `json:"trails,omitempty"` - - // Note: the proof_details top level field can be ignored here because it is a 'oneof' - MerkleLogCommit json.RawMessage `json:"merklelog_commit,omitempty"` - }{} - - err := json.Unmarshal(eventJson, &entry) - if err != nil { - return nil, err - } - - // get the merklelog commit info - merkleLogCommit := &assets.MerkleLogCommit{} - err = protojson.Unmarshal(entry.MerkleLogCommit, merkleLogCommit) - if err != nil { - return nil, err - } - - // get the logID from the event log tenant - logUuid := strings.TrimPrefix(logTenant, "tenant/") - logId, err := uuid.Parse(logUuid) - if err != nil { - return nil, err - } - - // get the extra bytes - extraBytes, err := NewEventsV1ExtraBytes(entry.OriginTenant) - if err != nil { - return nil, err - } - - // get the serialized bytes - serializableEvent := eventsv1.SerializableEvent{ - Attributes: entry.Attributes, - Trails: entry.Trails, - } - serializedBytes, err := serializableEvent.Serialize() - if err != nil { - return nil, err - } - - return &EventsV1AppEntry{ - AppEntry: &AppEntry{ - appID: entry.Identity, - logID: logId[:], - mmrEntryFields: &MMREntryFields{ - domain: byte(0), - serializedBytes: serializedBytes, - }, - extraBytes: extraBytes, - merkleLogCommit: merkleLogCommit, - }, - }, nil -} - -// NewEventsV1ExtraBytes generates the extra bytes for an eventv1 event -// given the origin tenant of the event. -// -// NOTE: the extraBytes will always be padded to 24 bytes -func NewEventsV1ExtraBytes(originTenant string) ([]byte, error) { - - extraBytes := make([]byte, ExtraBytesSize) - - extraBytes[0] = EventsV1AppDomain - - originTenantUuidStr := strings.TrimPrefix(originTenant, "tenant/") - - originTenantUuid, err := uuid.Parse(originTenantUuidStr) - if err != nil { - return nil, err - } - - copy(extraBytes[1:len(originTenantUuid)+1], originTenantUuid[:]) - - return extraBytes, nil -} diff --git a/logverification/app/logversion0.go b/logverification/app/logversion0.go index 9acaacf..08e710d 100644 --- a/logverification/app/logversion0.go +++ b/logverification/app/logversion0.go @@ -28,11 +28,7 @@ func NewLogVersion0Hasher() *LogVersion0Hasher { // - domain separator is 0 for plain leaf nodes (events) // - id timestamp is the timestamp id found on the event merklelog entry // - simplehashv3 is the datatrails simplehash v3 schema for hashing datatrails events -func (h *LogVersion0Hasher) HashEvent(eventJson []byte) ([]byte, error) { - assetsAppEntry, err := NewAssetsV2AppEntry(eventJson) - if err != nil { - return nil, err - } +func (h *LogVersion0Hasher) HashEvent(eventJson []byte, idTimestamp []byte) ([]byte, error) { simplehashv3Hasher := simplehash.NewHasherV3() v3Event, err := simplehash.V3FromEventJSON(eventJson) @@ -41,7 +37,7 @@ func (h *LogVersion0Hasher) HashEvent(eventJson []byte) ([]byte, error) { } // the idCommitted is in hex from the event, we need to convert it to uint64 - idCommitted, _, err := massifs.SplitIDTimestampHex(assetsAppEntry.IDTimestamp()) + idCommitted, _, err := massifs.SplitIDTimestampBytes(idTimestamp) if err != nil { return nil, err } diff --git a/logverification/app/logversion0_test.go b/logverification/app/logversion0_test.go deleted file mode 100644 index 9e07176..0000000 --- a/logverification/app/logversion0_test.go +++ /dev/null @@ -1,44 +0,0 @@ -package app - -import ( - "encoding/hex" - "testing" - - "github.com/stretchr/testify/assert" -) - -// TestLogVersion0Hash tests: -// -// 1. known answer test (KAT) for generating the hash of a test event. -func TestLogVersion0Hash(t *testing.T) { - type args struct { - eventJson []byte - } - tests := []struct { - name string - args args - expected []byte - err error - }{ - { - name: "positive (kat)", - args: args{ - eventJson: []byte(testEventJson), - }, - expected: []byte{117, 200, 223, 187, 85, 37, 16, 136, 187, 12, 16, 215, 5, 98, 144, 115, 43, 22, 136, 203, 199, 129, 140, 125, 143, 252, 92, 83, 186, 100, 230, 149}, - err: nil, - }, - } - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - hasher := LogVersion0Hasher{} - actual, err := hasher.HashEvent(test.args.eventJson) - - hexString := hex.EncodeToString(actual) - assert.NotNil(t, hexString) - - assert.Equal(t, test.err, err) - assert.Equal(t, test.expected, actual) - }) - } -} diff --git a/logverification/app/massifgetteroptions.go b/logverification/app/massifgetteroptions.go index 8feac43..ffb9dd8 100644 --- a/logverification/app/massifgetteroptions.go +++ b/logverification/app/massifgetteroptions.go @@ -1,7 +1,6 @@ package app import ( - "github.com/datatrails/go-datatrails-common/azblob" "github.com/datatrails/go-datatrails-merklelog/massifs" ) @@ -13,8 +12,6 @@ import ( type MassifGetterOptions struct { *MassifOptions - azblobReader azblob.Reader - massifGetter MassifGetter massifContext *massifs.MassifContext @@ -39,16 +36,6 @@ func WithMassifReader(massifReader MassifGetter, massifOpts ...MassifOption) Mas } } -// WithAzBlobReader is an option that ensures the given azblob reader is used -// to obtain the massif for the app entry. -func WithAzblobReader(azblobReader azblob.Reader, massifOpts ...MassifOption) MassifGetterOption { - return func(mo *MassifGetterOptions) { - mo.azblobReader = azblobReader - opts := ParseMassifOptions(massifOpts...) - mo.MassifOptions = &opts - } -} - // ParseMassifGetterOptions parses the given options into a MassifGetterOptions struct func ParseMassifGetterOptions(options ...MassifGetterOption) MassifGetterOptions { massifOptions := MassifGetterOptions{ diff --git a/logverification/massif.go b/logverification/massif.go index 4115e2c..7fa7aa6 100644 --- a/logverification/massif.go +++ b/logverification/massif.go @@ -5,7 +5,6 @@ import ( "errors" "time" - "github.com/datatrails/go-datatrails-logverification/logverification/app" "github.com/datatrails/go-datatrails-merklelog/massifs" ) @@ -41,18 +40,6 @@ func Massif(mmrIndex uint64, massifReader MassifGetter, tenantId string, massifH return &massif, nil } -// ChooseHashingSchema chooses the hashing schema based on the log version in the massif blob start record. -// See [Massif Basic File Format](https://github.com/datatrails/epic-8120-scalable-proof-mechanisms/blob/main/mmr/forestrie-massifs.md#massif-basic-file-format) -func ChooseHashingSchema(massifStart massifs.MassifStart) (EventHasher, error) { - - switch massifStart.Version { - case 0: - return app.NewLogVersion0Hasher(), nil - default: - return nil, errors.New("no hashing scheme for log version") - } -} - // UpdateMassifContext, updates the given massifContext to the massif that stores // // the given mmrIndex for the given tenant. diff --git a/logverification/validation.go b/logverification/validation.go index a045aec..5ab67af 100644 --- a/logverification/validation.go +++ b/logverification/validation.go @@ -31,10 +31,6 @@ func Validate(appEntry app.AppEntryGetter) error { return ErrNonEmptyTenantIDRequired } - if appEntry.IDTimestamp() == "" { - return ErrIdTimestampRequired - } - return nil } diff --git a/logverification/validation_test.go b/logverification/validation_test.go index f49626c..1cf9cef 100644 --- a/logverification/validation_test.go +++ b/logverification/validation_test.go @@ -61,31 +61,14 @@ func TestVerifiableEvent_Validate(t *testing.T) { }, expectedErr: ErrNonEmptyTenantIDRequired, }, - { - // NOTE: this can happen if the commit is empty, so covers that case as well - name: "missing idtimestamp returns specific error", - fields: fields{ - appID: "event/7189fa3d-9af1-40b1-975c-70f792142a82", - logID: []byte{0, 110, 33, 215, 99, 215, 71, 187, 154, 126, 13, 181, 86, 33, 49, 127}, // tenant/006e21d7-63d7-47bb-9a7e-0db55621317f - mmrEntryFields: nil, - merkleLogCommit: &assets.MerkleLogCommit{ - Index: uint64(0), - Idtimestamp: "", - }, - }, - expectedErr: ErrIdTimestampRequired, - }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - e := &app.AssetsV2AppEntry{ - AppEntry: app.NewAppEntry( - tt.fields.appID, - tt.fields.logID, - []byte{}, - tt.fields.mmrEntryFields, - tt.fields.merkleLogCommit), - } + e := app.NewAppEntry( + tt.fields.appID, + tt.fields.logID, + tt.fields.mmrEntryFields, + tt.fields.merkleLogCommit.Index) err := Validate(e) assert.ErrorIs(t, err, tt.expectedErr) diff --git a/logverification/verifylist.go b/logverification/verifylist.go index c85b017..d0e895f 100644 --- a/logverification/verifylist.go +++ b/logverification/verifylist.go @@ -344,7 +344,7 @@ func VerifyAppEntryInList( return Unknown, err } - mmrEntry, err := appEntry.MMREntry() + mmrEntry, err := appEntry.MMREntry(app.WithMassifContext(massifContext)) if err != nil { return Unknown, err } From 41518c0d88f377af55a9f0fd42cb5cab7b71f6aa Mon Sep 17 00:00:00 2001 From: jgough Date: Wed, 15 Jan 2025 18:41:28 +0000 Subject: [PATCH 02/10] fixup --- go.mod | 18 +++++++------- go.sum | 36 ++++++++++++++-------------- integrationsupport/testcontext.go | 17 ++++++++++++- logverification/app/appentry.go | 7 ++++++ logverification/app/appentry_test.go | 2 +- logverification/app/logversion0.go | 5 +++- logverification/verifylist_test.go | 33 +++++++++++++++++++++---- 7 files changed, 84 insertions(+), 34 deletions(-) diff --git a/go.mod b/go.mod index af850ae..e100e8e 100644 --- a/go.mod +++ b/go.mod @@ -3,12 +3,12 @@ module github.com/datatrails/go-datatrails-logverification go 1.23.0 require ( - github.com/datatrails/go-datatrails-common v0.18.1 + github.com/datatrails/go-common-avid-api/api v0.0.2 + github.com/datatrails/go-datatrails-common v0.18.3 github.com/datatrails/go-datatrails-common-api-gen v0.6.1 github.com/datatrails/go-datatrails-merklelog/massifs v0.3.1 github.com/datatrails/go-datatrails-merklelog/mmr v0.1.1 github.com/datatrails/go-datatrails-merklelog/mmrtesting v0.1.0 - github.com/datatrails/go-datatrails-serialization/eventsv1 v0.0.2 github.com/datatrails/go-datatrails-simplehash v0.0.5 github.com/google/uuid v1.6.0 github.com/stretchr/testify v1.10.0 @@ -52,12 +52,12 @@ require ( github.com/zeebo/bencode v1.0.0 // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.27.0 // indirect - golang.org/x/crypto v0.25.0 // indirect - golang.org/x/net v0.27.0 // indirect - golang.org/x/sys v0.22.0 // indirect - golang.org/x/text v0.16.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 // indirect - google.golang.org/grpc v1.65.0 // indirect + golang.org/x/crypto v0.26.0 // indirect + golang.org/x/net v0.28.0 // indirect + golang.org/x/sys v0.24.0 // indirect + golang.org/x/text v0.19.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20241104194629-dd2ea8efbc28 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20241021214115-324edc3d5d38 // indirect + google.golang.org/grpc v1.67.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index ce5e1a9..4c46a0a 100644 --- a/go.sum +++ b/go.sum @@ -40,8 +40,10 @@ github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUM github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 h1:XHOnouVk1mxXfQidrMEnLlPk9UMeRtyBTnEFtxkV0kU= github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI= -github.com/datatrails/go-datatrails-common v0.18.1 h1:WYRQPFT0w+9o/WFrEQfjUnBY9UbBijoWmcmJEHGEXTY= -github.com/datatrails/go-datatrails-common v0.18.1/go.mod h1:YUUAwrD7SQFXverHUxt2subZxTfSp76zUHxtmijNlvM= +github.com/datatrails/go-common-avid-api/api v0.0.2 h1:dXR0RinajCU9kVoIBpPSa300JsHHtFRhsSQWSfN3Ig4= +github.com/datatrails/go-common-avid-api/api v0.0.2/go.mod h1:T7zGBOn9HAx7nCGi/524MQwSQ1FYvADgeKTC2XneC8M= +github.com/datatrails/go-datatrails-common v0.18.3 h1:9h/8skTl1yCV/SeNRwYLETPZjikjYgKxJX65wXy12BM= +github.com/datatrails/go-datatrails-common v0.18.3/go.mod h1:YUUAwrD7SQFXverHUxt2subZxTfSp76zUHxtmijNlvM= github.com/datatrails/go-datatrails-common-api-gen v0.6.1 h1:rkzx2FBdTTNirLNLWHpXRme3GrOssPP27reQUwdFAJc= github.com/datatrails/go-datatrails-common-api-gen v0.6.1/go.mod h1:rTMGdMdu5M6mGpbXZy1D84cBTGE8JwsDH6BYh9LJlmA= github.com/datatrails/go-datatrails-merklelog/massifs v0.3.1 h1:RR1FVJ85iCrZIoMzcfxPLZsPCYl7XvlZ4S8sm2TxFi8= @@ -50,8 +52,6 @@ github.com/datatrails/go-datatrails-merklelog/mmr v0.1.1 h1:Ro2fYdDYxGGcPmudYuvP github.com/datatrails/go-datatrails-merklelog/mmr v0.1.1/go.mod h1:B/Kkz4joZTiTz0q/9FFAgHR+Tcn6UxtphMuCzamAc9Q= github.com/datatrails/go-datatrails-merklelog/mmrtesting v0.1.0 h1:q9RXtAGydXKSJjARnFObNu743cbfIOfERTXiiVa2tF4= github.com/datatrails/go-datatrails-merklelog/mmrtesting v0.1.0/go.mod h1:rWFjeK1NU7qnhl9+iKdjASpw/CkPwDAOPHsERYR7uEQ= -github.com/datatrails/go-datatrails-serialization/eventsv1 v0.0.2 h1:yEk+0KvWkn/xYbf3WgdFCAZNkLE4pze9ySqeCr6Pnos= -github.com/datatrails/go-datatrails-serialization/eventsv1 v0.0.2/go.mod h1:9i6Tip2lIXwSZ3SxP7XEhU2eQ9zkpxhEBmPmlOGqv/8= github.com/datatrails/go-datatrails-simplehash v0.0.5 h1:igu4QRYO87RQXrJlqSm3fgMA2Q0F4jglWqBlfvKrXKQ= github.com/datatrails/go-datatrails-simplehash v0.0.5/go.mod h1:XuOwViwdL+dyz7fGYIjaByS1ElMFsrVI0goKX0bNimA= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -142,8 +142,8 @@ golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5y golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= -golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30= -golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M= +golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw= +golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -152,8 +152,8 @@ golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= -golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= -golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= +golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE= +golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -166,8 +166,8 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= -golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg= +golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= @@ -180,19 +180,19 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= +golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094 h1:0+ozOGcrp+Y8Aq8TLNN2Aliibms5LEzsq99ZZmAGYm0= -google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094/go.mod h1:fJ/e3If/Q67Mj99hin0hMhiNyCRmt6BQ2aWIJshUSJw= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 h1:BwIjyKYGsK9dMCBOorzRri8MQwmi7mT9rGHsCEinZkA= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY= -google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc= -google.golang.org/grpc v1.65.0/go.mod h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ= +google.golang.org/genproto/googleapis/api v0.0.0-20241104194629-dd2ea8efbc28 h1:M0KvPgPmDZHPlbRbaNU1APr28TvwvvdUPlSv7PUvy8g= +google.golang.org/genproto/googleapis/api v0.0.0-20241104194629-dd2ea8efbc28/go.mod h1:dguCy7UOdZhTvLzDyt15+rOrawrpM4q7DD9dQ1P11P4= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241021214115-324edc3d5d38 h1:zciRKQ4kBpFgpfC5QQCVtnnNAcLIqweL7plyZRQHVpI= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241021214115-324edc3d5d38/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= +google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E= +google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= google.golang.org/protobuf v1.35.2 h1:8Ar7bF+apOIoThw1EdZl0p1oWvMqTHmpA2fRTyZO8io= google.golang.org/protobuf v1.35.2/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/integrationsupport/testcontext.go b/integrationsupport/testcontext.go index a246b42..47bb5fd 100644 --- a/integrationsupport/testcontext.go +++ b/integrationsupport/testcontext.go @@ -10,11 +10,13 @@ import ( "strings" "testing" + "github.com/datatrails/go-common-avid-api/api/tenancies/v1/tenancies" "github.com/datatrails/go-datatrails-common-api-gen/assets/v2/assets" dtcose "github.com/datatrails/go-datatrails-common/cose" "github.com/datatrails/go-datatrails-merklelog/massifs" "github.com/datatrails/go-datatrails-merklelog/mmrtesting" "github.com/datatrails/go-datatrails-simplehash/simplehash" + "github.com/google/uuid" "github.com/stretchr/testify/require" "github.com/veraison/go-cose" ) @@ -105,8 +107,21 @@ func GenerateTenantLog(tc *mmrtesting.TestContext, g TestGenerator, eventTotal i // mmrIndex is equal to the count of all nodes mmrIndex := mc.RangeCount() + extraBytes := []byte{ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, // 24 bytes + } + + tenantUUIDStr := tenancies.UuidFromIdentity(ev.TenantIdentity) + tenantUUID, err := uuid.Parse(tenantUUIDStr) + require.NoError(tc.T, err) + + logID, err := tenantUUID.MarshalBinary() + require.NoError(tc.T, err) + // add the generated event to the mmr - _, err1 = mc.AddHashedLeaf(sha256.New(), idTimestamp, nil, []byte(ev.TenantIdentity), []byte(ev.GetIdentity()), leafValue) + _, err1 = mc.AddHashedLeaf(sha256.New(), idTimestamp, extraBytes, logID, []byte(ev.GetIdentity()), leafValue) if err1 != nil { if errors.Is(err1, massifs.ErrMassifFull) { var err2 error diff --git a/logverification/app/appentry.go b/logverification/app/appentry.go index 3f1af30..d462ab7 100644 --- a/logverification/app/appentry.go +++ b/logverification/app/appentry.go @@ -104,6 +104,13 @@ type MMREntryFields struct { serializedBytes []byte } +func NewMMREntryFields(domain byte, serializedBytes []byte) *MMREntryFields { + return &MMREntryFields{ + domain: domain, + serializedBytes: serializedBytes, + } +} + // AppEntry is the app provided data for a corresponding log entry. // // It contains key information for verifying inclusion of the corresponding log entry. diff --git a/logverification/app/appentry_test.go b/logverification/app/appentry_test.go index 712f224..a0fb6de 100644 --- a/logverification/app/appentry_test.go +++ b/logverification/app/appentry_test.go @@ -125,7 +125,7 @@ func TestNewAppEntry(t *testing.T) { // TestAppEntry_MMRSalt tests: // -// 1. Known Answer Test for MMRSalt for log version 0. +// 1. Known Answer Test for MMRSalt for log version 1. func TestAppEntry_MMRSalt(t *testing.T) { testMassifContext := testMassifContext(t) diff --git a/logverification/app/logversion0.go b/logverification/app/logversion0.go index 08e710d..3d7b384 100644 --- a/logverification/app/logversion0.go +++ b/logverification/app/logversion0.go @@ -36,8 +36,11 @@ func (h *LogVersion0Hasher) HashEvent(eventJson []byte, idTimestamp []byte) ([]b return nil, err } + idTimestampWithEpoch := []byte{0} + idTimestampWithEpoch = append(idTimestampWithEpoch, idTimestamp...) + // the idCommitted is in hex from the event, we need to convert it to uint64 - idCommitted, _, err := massifs.SplitIDTimestampBytes(idTimestamp) + idCommitted, _, err := massifs.SplitIDTimestampBytes(idTimestampWithEpoch) if err != nil { return nil, err } diff --git a/logverification/verifylist_test.go b/logverification/verifylist_test.go index 67ec32b..83debda 100644 --- a/logverification/verifylist_test.go +++ b/logverification/verifylist_test.go @@ -6,12 +6,14 @@ import ( "fmt" "testing" + "github.com/datatrails/go-common-avid-api/api/tenancies/v1/tenancies" "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/logger" "github.com/datatrails/go-datatrails-logverification/integrationsupport" "github.com/datatrails/go-datatrails-logverification/logverification/app" "github.com/datatrails/go-datatrails-merklelog/mmrtesting" + "github.com/google/uuid" "github.com/stretchr/testify/require" // TestVerifyListIntegration demonstrates how to verify the completeness of a list of events against a // DataTrails Merkle log. @@ -32,11 +34,34 @@ func serializeTestEvents(t *testing.T, events []*assets.EventResponse) []byte { // protoEventsToVerifiableEvents converts from he internally used proto EventResponse type // that our event generator returns, to the VerifiableEvent expected by logverification. func protoEventsToVerifiableEvents(t *testing.T, events []*assets.EventResponse) []app.VerifiableAppEntry { - eventJsonList := serializeTestEvents(t, events) - result, err := app.NewAssetsV2AppEntries(eventJsonList) - require.NoError(t, err) - return result + appEntries := []app.VerifiableAppEntry{} + + for _, event := range events { + + marshaller := assets.NewFlatMarshalerForEvents() + eventJson, err := marshaller.Marshal(event) + require.NoError(t, err) + + tenantUUIDStr := tenancies.UuidFromIdentity(event.TenantIdentity) + tenantUUID, err := uuid.Parse(tenantUUIDStr) + require.NoError(t, err) + + logID, err := tenantUUID.MarshalBinary() + require.NoError(t, err) + + appEntry := app.NewAppEntry( + event.Identity, + logID, + app.NewMMREntryFields(0, eventJson), + event.MerklelogEntry.Commit.Index, + ) + + appEntries = append(appEntries, appEntry) + + } + + return appEntries } func TestVerifyListIntegration(t *testing.T) { From c6eb1baba0b43adf4c8e7de2dc1bcbc631f73e9e Mon Sep 17 00:00:00 2001 From: jgough Date: Thu, 16 Jan 2025 09:02:54 +0000 Subject: [PATCH 03/10] fixup --- logverification/app/appentry.go | 30 ++++++++++++++-------------- logverification/app/appentry_test.go | 2 ++ 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/logverification/app/appentry.go b/logverification/app/appentry.go index d462ab7..6c3cc02 100644 --- a/logverification/app/appentry.go +++ b/logverification/app/appentry.go @@ -149,16 +149,6 @@ func NewAppEntry( return appEntry } -// MMRIndex gets the mmr index of the corresponding log entry. -func (ae *AppEntry) MMRIndex() uint64 { - return ae.mmrIndex -} - -// SerializedBytes gets the serialized bytes used to generate id of the corresponding mmr entry. -func (ae *AppEntry) SerializedBytes() []byte { - return ae.mmrEntryFields.serializedBytes -} - // AppID gets the app id of the corresponding log entry. func (ae *AppEntry) AppID() string { return ae.appID @@ -169,6 +159,21 @@ func (ae *AppEntry) LogID() []byte { return ae.logID } +// Domain gets the domain byte used to derive the mmr entry. +func (ae *AppEntry) Domain() byte { + return ae.mmrEntryFields.domain +} + +// SerializedBytes gets the serialized bytes used to generate hash of the corresponding mmr entry. +func (ae *AppEntry) SerializedBytes() []byte { + return ae.mmrEntryFields.serializedBytes +} + +// MMRIndex gets the mmr index of the corresponding log entry. +func (ae *AppEntry) MMRIndex() uint64 { + return ae.mmrIndex +} + // LogTenant returns the Log tenant that committed this app entry to the log // as a tenant identity. func (ae *AppEntry) LogTenant() (string, error) { @@ -221,11 +226,6 @@ func (ae *AppEntry) IDTimestamp(options ...MassifGetterOption) ([]byte, error) { return massifs.GetIdtimestamp(trieEntry, 0, 0), nil } -// Domain gets the domain byte used to derive the mmr entry. -func (ae *AppEntry) Domain() byte { - return ae.mmrEntryFields.domain -} - // MMRSalt derives the MMR Salt of the corresponding log entry from the app data. // MMRSalt is the datatrails provided fields included on the MMR Entry. // diff --git a/logverification/app/appentry_test.go b/logverification/app/appentry_test.go index a0fb6de..d467ef4 100644 --- a/logverification/app/appentry_test.go +++ b/logverification/app/appentry_test.go @@ -14,6 +14,8 @@ import ( // // the first entry is a known log version 0 entry // the seconds entry is a known log version 1 entry +// +// TODO: Add actual KAT data func testMassifContext(t *testing.T) *massifs.MassifContext { start := massifs.MassifStart{ From e5fcea5bb3e17a51fbc88d73e459fc608467d8ca Mon Sep 17 00:00:00 2001 From: jgough Date: Thu, 16 Jan 2025 09:08:49 +0000 Subject: [PATCH 04/10] fixup --- integrationsupport/testcontext.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/integrationsupport/testcontext.go b/integrationsupport/testcontext.go index 47bb5fd..4ecfda2 100644 --- a/integrationsupport/testcontext.go +++ b/integrationsupport/testcontext.go @@ -10,7 +10,6 @@ import ( "strings" "testing" - "github.com/datatrails/go-common-avid-api/api/tenancies/v1/tenancies" "github.com/datatrails/go-datatrails-common-api-gen/assets/v2/assets" dtcose "github.com/datatrails/go-datatrails-common/cose" "github.com/datatrails/go-datatrails-merklelog/massifs" @@ -113,7 +112,7 @@ func GenerateTenantLog(tc *mmrtesting.TestContext, g TestGenerator, eventTotal i 0, 0, 0, 0, 0, 0, 0, 0, // 24 bytes } - tenantUUIDStr := tenancies.UuidFromIdentity(ev.TenantIdentity) + tenantUUIDStr := strings.TrimPrefix(ev.TenantIdentity, "tenant/") tenantUUID, err := uuid.Parse(tenantUUIDStr) require.NoError(tc.T, err) From 3e87190b3867b0a278b371a7a44c0a420f06bebf Mon Sep 17 00:00:00 2001 From: jgough Date: Thu, 16 Jan 2025 09:15:30 +0000 Subject: [PATCH 05/10] fixup --- go.mod | 1 - go.sum | 2 -- logverification/verifylist_test.go | 4 ++-- 3 files changed, 2 insertions(+), 5 deletions(-) diff --git a/go.mod b/go.mod index e100e8e..275f7af 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,6 @@ module github.com/datatrails/go-datatrails-logverification go 1.23.0 require ( - github.com/datatrails/go-common-avid-api/api v0.0.2 github.com/datatrails/go-datatrails-common v0.18.3 github.com/datatrails/go-datatrails-common-api-gen v0.6.1 github.com/datatrails/go-datatrails-merklelog/massifs v0.3.1 diff --git a/go.sum b/go.sum index 4c46a0a..8c05b44 100644 --- a/go.sum +++ b/go.sum @@ -40,8 +40,6 @@ github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUM github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 h1:XHOnouVk1mxXfQidrMEnLlPk9UMeRtyBTnEFtxkV0kU= github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI= -github.com/datatrails/go-common-avid-api/api v0.0.2 h1:dXR0RinajCU9kVoIBpPSa300JsHHtFRhsSQWSfN3Ig4= -github.com/datatrails/go-common-avid-api/api v0.0.2/go.mod h1:T7zGBOn9HAx7nCGi/524MQwSQ1FYvADgeKTC2XneC8M= github.com/datatrails/go-datatrails-common v0.18.3 h1:9h/8skTl1yCV/SeNRwYLETPZjikjYgKxJX65wXy12BM= github.com/datatrails/go-datatrails-common v0.18.3/go.mod h1:YUUAwrD7SQFXverHUxt2subZxTfSp76zUHxtmijNlvM= github.com/datatrails/go-datatrails-common-api-gen v0.6.1 h1:rkzx2FBdTTNirLNLWHpXRme3GrOssPP27reQUwdFAJc= diff --git a/logverification/verifylist_test.go b/logverification/verifylist_test.go index 83debda..8f899e7 100644 --- a/logverification/verifylist_test.go +++ b/logverification/verifylist_test.go @@ -4,9 +4,9 @@ package logverification import ( "fmt" + "strings" "testing" - "github.com/datatrails/go-common-avid-api/api/tenancies/v1/tenancies" "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/logger" @@ -43,7 +43,7 @@ func protoEventsToVerifiableEvents(t *testing.T, events []*assets.EventResponse) eventJson, err := marshaller.Marshal(event) require.NoError(t, err) - tenantUUIDStr := tenancies.UuidFromIdentity(event.TenantIdentity) + tenantUUIDStr := strings.TrimPrefix(event.TenantIdentity, "/tenant") tenantUUID, err := uuid.Parse(tenantUUIDStr) require.NoError(t, err) From 087b0ce3a7e23f158920cc4bf70d4f9c63c17e63 Mon Sep 17 00:00:00 2001 From: jgough Date: Thu, 16 Jan 2025 09:16:17 +0000 Subject: [PATCH 06/10] fixup --- logverification/verifylist_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/logverification/verifylist_test.go b/logverification/verifylist_test.go index 8f899e7..3b1ef74 100644 --- a/logverification/verifylist_test.go +++ b/logverification/verifylist_test.go @@ -43,7 +43,7 @@ func protoEventsToVerifiableEvents(t *testing.T, events []*assets.EventResponse) eventJson, err := marshaller.Marshal(event) require.NoError(t, err) - tenantUUIDStr := strings.TrimPrefix(event.TenantIdentity, "/tenant") + tenantUUIDStr := strings.TrimPrefix(event.TenantIdentity, "tenant/") tenantUUID, err := uuid.Parse(tenantUUIDStr) require.NoError(t, err) From c1e2907d65b1fb9080129847a545c40343d69c51 Mon Sep 17 00:00:00 2001 From: jgough Date: Thu, 16 Jan 2025 09:36:35 +0000 Subject: [PATCH 07/10] fixup linting --- integrationsupport/testcontext.go | 6 ++++-- logverification/app/appentry.go | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/integrationsupport/testcontext.go b/integrationsupport/testcontext.go index 4ecfda2..79e0893 100644 --- a/integrationsupport/testcontext.go +++ b/integrationsupport/testcontext.go @@ -113,10 +113,12 @@ func GenerateTenantLog(tc *mmrtesting.TestContext, g TestGenerator, eventTotal i } tenantUUIDStr := strings.TrimPrefix(ev.TenantIdentity, "tenant/") - tenantUUID, err := uuid.Parse(tenantUUIDStr) + var tenantUUID uuid.UUID + tenantUUID, err = uuid.Parse(tenantUUIDStr) require.NoError(tc.T, err) - logID, err := tenantUUID.MarshalBinary() + var logID []byte + logID, err = tenantUUID.MarshalBinary() require.NoError(tc.T, err) // add the generated event to the mmr diff --git a/logverification/app/appentry.go b/logverification/app/appentry.go index 6c3cc02..e793c5c 100644 --- a/logverification/app/appentry.go +++ b/logverification/app/appentry.go @@ -281,12 +281,14 @@ func (ae *AppEntry) MMREntry(options ...MassifGetterOption) ([]byte, error) { if logVersion0 { hasher := LogVersion0Hasher{} - idTimestamp, err := ae.IDTimestamp(WithMassifContext(massifContext)) + var idTimestamp []byte + idTimestamp, err = ae.IDTimestamp(WithMassifContext(massifContext)) if err != nil { return nil, err } - eventHash, err := hasher.HashEvent(ae.mmrEntryFields.serializedBytes, idTimestamp) + var eventHash []byte + eventHash, err = hasher.HashEvent(ae.mmrEntryFields.serializedBytes, idTimestamp) if err != nil { return nil, err } From 29c8e200a85cc016f10a5a7d752e236f046d0877 Mon Sep 17 00:00:00 2001 From: jgough Date: Thu, 16 Jan 2025 10:03:16 +0000 Subject: [PATCH 08/10] fixup --- logverification/app/appentry.go | 49 ---------------------------- logverification/app/appentry_test.go | 12 +++---- logverification/leafrange.go | 2 +- logverification/validation.go | 2 +- logverification/validation_test.go | 2 +- logverification/verifylist.go | 4 +-- 6 files changed, 10 insertions(+), 61 deletions(-) diff --git a/logverification/app/appentry.go b/logverification/app/appentry.go index e793c5c..66b468e 100644 --- a/logverification/app/appentry.go +++ b/logverification/app/appentry.go @@ -45,55 +45,6 @@ const ( IDTimestapSizeBytes = 8 ) -// AppEntryGetter gets fields from the app entry or derives -// -// fields from the app entry. -type AppEntryGetter interface { - AppID() string - LogID() []byte - LogTenant() (string, error) - Domain() byte - SerializedBytes() []byte - MMRIndex() uint64 - - MMRSalt(options ...MassifGetterOption) ([]byte, error) -} - -// MMREntryGetter gets an mmrEntry from the given serialized bytes and corresponding log entry -type MMREntryGetter interface { - MMREntry(options ...MassifGetterOption) ([]byte, error) -} - -// TrieEntryGetter gets the trie entry -type TrieEntryGetter interface { - ExtraBytes(options ...MassifGetterOption) ([]byte, error) - IDTimestamp(options ...MassifGetterOption) ([]byte, error) - TrieEntry(options ...MassifGetterOption) ([]byte, error) -} - -// AppEntryMassifGetter gets the massif for a specific app entry. -type AppEntryMassifGetter interface { - Massif(options ...MassifGetterOption) (*massifs.MassifContext, error) -} - -// AppEntryVerifier can be used to verify the inclusion of an app entry -// -// against its corresponding log entry. -type AppEntryVerifier interface { - Proof(options ...MassifGetterOption) ([][]byte, error) - VerifyProof(proof [][]byte, options ...MassifGetterOption) (bool, error) - VerifyInclusion(options ...MassifGetterOption) (bool, error) -} - -// VerifiableAppEntry includes all methods that could be needed for a verifiable app entry. -type VerifiableAppEntry interface { - AppEntryGetter - MMREntryGetter - TrieEntryGetter - AppEntryMassifGetter - AppEntryVerifier -} - // MMREntryFields are the fields that when hashed result in the MMR Entry type MMREntryFields struct { diff --git a/logverification/app/appentry_test.go b/logverification/app/appentry_test.go index d467ef4..82fb331 100644 --- a/logverification/app/appentry_test.go +++ b/logverification/app/appentry_test.go @@ -109,17 +109,15 @@ func TestNewAppEntry(t *testing.T) { test.args.mmrIndex, ) - appEntryGetter := AppEntryGetter(actual) - - assert.Equal(t, test.expected.appID, appEntryGetter.AppID()) - assert.Equal(t, test.expected.logID, appEntryGetter.LogID()) + assert.Equal(t, test.expected.appID, actual.AppID()) + assert.Equal(t, test.expected.logID, actual.LogID()) // mmr entry fields - assert.Equal(t, test.expected.mmrEntryFields.domain, appEntryGetter.Domain()) - assert.Equal(t, test.expected.mmrEntryFields.serializedBytes, appEntryGetter.SerializedBytes()) + assert.Equal(t, test.expected.mmrEntryFields.domain, actual.Domain()) + assert.Equal(t, test.expected.mmrEntryFields.serializedBytes, actual.SerializedBytes()) // mmr index - assert.Equal(t, test.expected.mmrIndex, appEntryGetter.MMRIndex()) + assert.Equal(t, test.expected.mmrIndex, actual.MMRIndex()) }) } diff --git a/logverification/leafrange.go b/logverification/leafrange.go index bdeddfb..285d1b4 100644 --- a/logverification/leafrange.go +++ b/logverification/leafrange.go @@ -15,7 +15,7 @@ import ( // events, that have been sorted from lowest mmr index to highest mmr index. // // Returns the lower and upper bound of the leaf indexes for the leaf range. -func LeafRange(sortedEvents []app.VerifiableAppEntry) (uint64, uint64) { +func LeafRange(sortedEvents []app.AppEntry) (uint64, uint64) { lowerBoundMMRIndex := sortedEvents[0].MMRIndex() lowerBoundLeafIndex := mmr.LeafCount(lowerBoundMMRIndex+1) - 1 // Note: LeafCount takes an mmrIndex here not a size diff --git a/logverification/validation.go b/logverification/validation.go index 5ab67af..78a306e 100644 --- a/logverification/validation.go +++ b/logverification/validation.go @@ -22,7 +22,7 @@ var ( // Validate performs basic validation on the AppEntryGetter, ensuring that critical fields // are present. -func Validate(appEntry app.AppEntryGetter) error { +func Validate(appEntry app.AppEntry) error { if appEntry.AppID() == "" { return ErrNonEmptyAppIDRequired } diff --git a/logverification/validation_test.go b/logverification/validation_test.go index 1cf9cef..85e07ec 100644 --- a/logverification/validation_test.go +++ b/logverification/validation_test.go @@ -70,7 +70,7 @@ func TestVerifiableEvent_Validate(t *testing.T) { tt.fields.mmrEntryFields, tt.fields.merkleLogCommit.Index) - err := Validate(e) + err := Validate(*e) assert.ErrorIs(t, err, tt.expectedErr) }) } diff --git a/logverification/verifylist.go b/logverification/verifylist.go index d0e895f..1289ea4 100644 --- a/logverification/verifylist.go +++ b/logverification/verifylist.go @@ -170,7 +170,7 @@ var ( * to be included on. E.g. the public tenant * for public events. */ -func VerifyList(reader azblob.Reader, appEntries []app.VerifiableAppEntry, options ...VerifyOption) ([]uint64, error) { +func VerifyList(reader azblob.Reader, appEntries []app.AppEntry, options ...VerifyOption) ([]uint64, error) { verifyOptions := ParseOptions(options...) @@ -238,7 +238,7 @@ func VerifyList(reader azblob.Reader, appEntries []app.VerifiableAppEntry, optio func VerifyAppEntryInList( hasher hash.Hash, leafIndex uint64, - appEntry app.VerifiableAppEntry, + appEntry app.AppEntry, reader massifs.MassifReader, massifContext *massifs.MassifContext, tenantID string, From 85874d7a96bcbd3f3c7e5fb10f0cdec7889f25f0 Mon Sep 17 00:00:00 2001 From: jgough Date: Thu, 16 Jan 2025 10:11:24 +0000 Subject: [PATCH 09/10] fixup --- logverification/verifylist_test.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/logverification/verifylist_test.go b/logverification/verifylist_test.go index 3b1ef74..d735cbb 100644 --- a/logverification/verifylist_test.go +++ b/logverification/verifylist_test.go @@ -33,9 +33,9 @@ func serializeTestEvents(t *testing.T, events []*assets.EventResponse) []byte { // protoEventsToVerifiableEvents converts from he internally used proto EventResponse type // that our event generator returns, to the VerifiableEvent expected by logverification. -func protoEventsToVerifiableEvents(t *testing.T, events []*assets.EventResponse) []app.VerifiableAppEntry { +func protoEventsToVerifiableEvents(t *testing.T, events []*assets.EventResponse) []app.AppEntry { - appEntries := []app.VerifiableAppEntry{} + appEntries := []app.AppEntry{} for _, event := range events { @@ -57,7 +57,7 @@ func protoEventsToVerifiableEvents(t *testing.T, events []*assets.EventResponse) event.MerklelogEntry.Commit.Index, ) - appEntries = append(appEntries, appEntry) + appEntries = append(appEntries, *appEntry) } From 3a54c0b74a1599934f9c3b10b324ac0641681379 Mon Sep 17 00:00:00 2001 From: jgough Date: Thu, 16 Jan 2025 10:21:34 +0000 Subject: [PATCH 10/10] fixup just massif context --- logverification/app/appentry.go | 123 ++++----------------- logverification/app/appentry_test.go | 2 +- logverification/app/massif.go | 41 ------- logverification/app/massifgetteroptions.go | 53 --------- logverification/app/massifoptions.go | 56 ---------- logverification/verifylist.go | 2 +- 6 files changed, 24 insertions(+), 253 deletions(-) delete mode 100644 logverification/app/massif.go delete mode 100644 logverification/app/massifgetteroptions.go delete mode 100644 logverification/app/massifoptions.go diff --git a/logverification/app/appentry.go b/logverification/app/appentry.go index 66b468e..9a19ec4 100644 --- a/logverification/app/appentry.go +++ b/logverification/app/appentry.go @@ -2,7 +2,6 @@ package app import ( "crypto/sha256" - "errors" "fmt" "github.com/datatrails/go-datatrails-merklelog/massifs" @@ -139,12 +138,7 @@ func (ae *AppEntry) LogTenant() (string, error) { } // TrieEntry gets the corresponding log trie entry for the app entry. -func (ae *AppEntry) TrieEntry(options ...MassifGetterOption) ([]byte, error) { - - massifContext, err := ae.Massif(options...) - if err != nil { - return nil, err - } +func (ae *AppEntry) TrieEntry(massifContext *massifs.MassifContext) ([]byte, error) { trieEntry, err := massifContext.GetTrieEntry(ae.MMRIndex()) if err != nil { @@ -156,9 +150,9 @@ func (ae *AppEntry) TrieEntry(options ...MassifGetterOption) ([]byte, error) { } // ExtraBytes gets the extrabytes of the corresponding log entry. -func (ae *AppEntry) ExtraBytes(options ...MassifGetterOption) ([]byte, error) { +func (ae *AppEntry) ExtraBytes(massifContext *massifs.MassifContext) ([]byte, error) { - trieEntry, err := ae.TrieEntry(options...) + trieEntry, err := ae.TrieEntry(massifContext) if err != nil { return nil, err } @@ -167,9 +161,9 @@ func (ae *AppEntry) ExtraBytes(options ...MassifGetterOption) ([]byte, error) { } // IDTimestamp gets the idtimestamp of the corresponding log entry. -func (ae *AppEntry) IDTimestamp(options ...MassifGetterOption) ([]byte, error) { +func (ae *AppEntry) IDTimestamp(massifContext *massifs.MassifContext) ([]byte, error) { - trieEntry, err := ae.TrieEntry(options...) + trieEntry, err := ae.TrieEntry(massifContext) if err != nil { return nil, err } @@ -181,16 +175,16 @@ func (ae *AppEntry) IDTimestamp(options ...MassifGetterOption) ([]byte, error) { // MMRSalt is the datatrails provided fields included on the MMR Entry. // // this is (extrabytes | idtimestamp) for any apps that adhere to log entry version 1. -func (ae *AppEntry) MMRSalt(options ...MassifGetterOption) ([]byte, error) { +func (ae *AppEntry) MMRSalt(massifContext *massifs.MassifContext) ([]byte, error) { mmrSalt := make([]byte, MMRSaltSize) - extraBytes, err := ae.ExtraBytes(options...) + extraBytes, err := ae.ExtraBytes(massifContext) if err != nil { return nil, err } - idTimestamp, err := ae.IDTimestamp(options...) + idTimestamp, err := ae.IDTimestamp(massifContext) if err != nil { return nil, err } @@ -208,17 +202,11 @@ func (ae *AppEntry) MMRSalt(options ...MassifGetterOption) ([]byte, error) { // - H( Domain | MMR Salt | Serialized Bytes) // // The MMR Salt is sourced from the corresponding log entry -func (ae *AppEntry) MMREntry(options ...MassifGetterOption) ([]byte, error) { +func (ae *AppEntry) MMREntry(massifContext *massifs.MassifContext) ([]byte, error) { logVersion0 := true - // first find the log version - massifContext, err := ae.Massif(options...) - if err != nil { - return nil, err - } - - extraBytes, err := ae.ExtraBytes(WithMassifContext(massifContext)) + extraBytes, err := ae.ExtraBytes(massifContext) if err != nil { return nil, err } @@ -233,7 +221,7 @@ func (ae *AppEntry) MMREntry(options ...MassifGetterOption) ([]byte, error) { hasher := LogVersion0Hasher{} var idTimestamp []byte - idTimestamp, err = ae.IDTimestamp(WithMassifContext(massifContext)) + idTimestamp, err = ae.IDTimestamp(massifContext) if err != nil { return nil, err } @@ -255,7 +243,7 @@ func (ae *AppEntry) MMREntry(options ...MassifGetterOption) ([]byte, error) { hasher.Write([]byte{ae.mmrEntryFields.domain}) // mmr salt - mmrSalt, err := ae.MMRSalt() + mmrSalt, err := ae.MMRSalt(massifContext) if err != nil { return nil, err } @@ -269,68 +257,13 @@ func (ae *AppEntry) MMREntry(options ...MassifGetterOption) ([]byte, error) { } -/** Massif gets the massif context, for the massif of the corresponding log entry from the app data. - * - * The following massif options can be used, in priority order: - * - WithMassifContext - * - WithMassifReader - * - * Example WithMassifReader: - * - * WithMassifReader( - * reader, - * WithMassifTenantId("tenant/foo"), - * WithMassifHeight(14), - * ) - */ -func (ae *AppEntry) Massif(options ...MassifGetterOption) (*massifs.MassifContext, error) { - - massifOptions := ParseMassifGetterOptions(options...) - - // first check if the options give a massif context to use, and use that - if massifOptions.massifContext != nil { - return massifOptions.massifContext, nil - } - - // now check if we have a massif reader - if massifOptions.massifGetter == nil { - return nil, errors.New("no way of determining massif of app entry, please provide either a massif context or massif getter") - - } - - massifReader := massifOptions.massifGetter - massifHeight := massifOptions.MassifHeight - - logIdentity := massifOptions.TenantId - // if the log identity is not given, attempt to find it from the logId - if massifOptions.TenantId == "" { - // find the tenant log from the logID - logUuid, err := uuid.FromBytes(ae.logID) - if err != nil { - return nil, err - } - - // log identity is currently `tenant/logid` - logIdentity = fmt.Sprintf("tenant/%s", logUuid.String()) - } - - return Massif(ae.mmrIndex, massifReader, logIdentity, massifHeight) - -} - // Proof gets the inclusion proof of the corresponding log entry for the app data. -func (ae *AppEntry) Proof(options ...MassifGetterOption) ([][]byte, error) { - - massif, err := ae.Massif(options...) - - if err != nil { - return nil, err - } +func (ae *AppEntry) Proof(massifContext *massifs.MassifContext) ([][]byte, error) { // Get the size of the complete tenant MMR - mmrSize := massif.RangeCount() + mmrSize := massifContext.RangeCount() - proof, err := mmr.InclusionProof(massif, mmrSize-1, ae.MMRIndex()) + proof, err := mmr.InclusionProof(massifContext, mmrSize-1, ae.MMRIndex()) if err != nil { return nil, err } @@ -339,25 +272,19 @@ func (ae *AppEntry) Proof(options ...MassifGetterOption) ([][]byte, error) { } // VerifyProof verifies the given inclusion proof of the corresponding log entry for the app data. -func (ae *AppEntry) VerifyProof(proof [][]byte, options ...MassifGetterOption) (bool, error) { - - massif, err := ae.Massif(options...) - - if err != nil { - return false, err - } +func (ae *AppEntry) VerifyProof(massifContext *massifs.MassifContext, proof [][]byte) (bool, error) { // Get the size of the complete tenant MMR - mmrSize := massif.RangeCount() + mmrSize := massifContext.RangeCount() hasher := sha256.New() - mmrEntry, err := ae.MMREntry() + mmrEntry, err := ae.MMREntry(massifContext) if err != nil { return false, err } - return mmr.VerifyInclusion(massif, hasher, mmrSize, mmrEntry, + return mmr.VerifyInclusion(massifContext, hasher, mmrSize, mmrEntry, ae.MMRIndex(), proof) } @@ -366,18 +293,12 @@ func (ae *AppEntry) VerifyProof(proof [][]byte, options ...MassifGetterOption) ( // against the corresponding log entry in immutable merkle log // // Returns true if the app entry is included on the log, otherwise false. -func (ae *AppEntry) VerifyInclusion(options ...MassifGetterOption) (bool, error) { - - massif, err := ae.Massif(options...) - - if err != nil { - return false, err - } +func (ae *AppEntry) VerifyInclusion(massifContext *massifs.MassifContext) (bool, error) { - proof, err := ae.Proof(WithMassifContext(massif)) + proof, err := ae.Proof(massifContext) if err != nil { return false, err } - return ae.VerifyProof(proof, WithMassifContext(massif)) + return ae.VerifyProof(massifContext, proof) } diff --git a/logverification/app/appentry_test.go b/logverification/app/appentry_test.go index 82fb331..0337936 100644 --- a/logverification/app/appentry_test.go +++ b/logverification/app/appentry_test.go @@ -159,7 +159,7 @@ func TestAppEntry_MMRSalt(t *testing.T) { mmrIndex: test.fields.mmrIndex, } - actual, err := ae.MMRSalt(WithMassifContext(testMassifContext)) + actual, err := ae.MMRSalt(testMassifContext) assert.Equal(t, test.err, err) assert.Equal(t, test.expected, actual) diff --git a/logverification/app/massif.go b/logverification/app/massif.go deleted file mode 100644 index 863d1b2..0000000 --- a/logverification/app/massif.go +++ /dev/null @@ -1,41 +0,0 @@ -package app - -import ( - "context" - "errors" - "time" - - "github.com/datatrails/go-datatrails-merklelog/massifs" -) - -const ( - contextTimeout = 30 * time.Second -) - -var ( - ErrNilMassifContext = errors.New("nil massif context") -) - -type MassifGetter interface { - GetMassif( - ctx context.Context, tenantIdentity string, massifIndex uint64, opts ...massifs.ReaderOption, - ) (massifs.MassifContext, error) -} - -// Massif gets the massif (blob) that contains the given mmrIndex, from azure blob storage -// -// defined by the azblob configuration. -func Massif(mmrIndex uint64, massifGetter MassifGetter, tenantId string, massifHeight uint8) (*massifs.MassifContext, error) { - - massifIndex := massifs.MassifIndexFromMMRIndex(massifHeight, mmrIndex) - - ctx, cancel := context.WithTimeout(context.Background(), contextTimeout) - defer cancel() - - massif, err := massifGetter.GetMassif(ctx, tenantId, massifIndex) - if err != nil { - return nil, err - } - - return &massif, nil -} diff --git a/logverification/app/massifgetteroptions.go b/logverification/app/massifgetteroptions.go deleted file mode 100644 index ffb9dd8..0000000 --- a/logverification/app/massifgetteroptions.go +++ /dev/null @@ -1,53 +0,0 @@ -package app - -import ( - "github.com/datatrails/go-datatrails-merklelog/massifs" -) - -/** - * Massif Options for the App are how the App Entries retrieve the correct massif to get data from their corresponding log entry. - */ - -// MassifGetterOptions how an app entry retrieves its massif -type MassifGetterOptions struct { - *MassifOptions - - massifGetter MassifGetter - - massifContext *massifs.MassifContext -} - -type MassifGetterOption func(*MassifGetterOptions) - -// WithMassifContext is an option that ensures the app entry uses the given -// -// massif context -func WithMassifContext(massifContext *massifs.MassifContext) MassifGetterOption { - return func(mo *MassifGetterOptions) { mo.massifContext = massifContext } -} - -// WithMassifReader is an option that ensures the given massif reader is used -// to obtain the massif for the app entry. -func WithMassifReader(massifReader MassifGetter, massifOpts ...MassifOption) MassifGetterOption { - return func(mo *MassifGetterOptions) { - mo.massifGetter = massifReader - opts := ParseMassifOptions(massifOpts...) - mo.MassifOptions = &opts - } -} - -// ParseMassifGetterOptions parses the given options into a MassifGetterOptions struct -func ParseMassifGetterOptions(options ...MassifGetterOption) MassifGetterOptions { - massifOptions := MassifGetterOptions{ - MassifOptions: &MassifOptions{ - NonLeafNode: false, // default to erroring on non leaf nodes - MassifHeight: DefaultMassifHeight, // set the default massif height first - }, - } - - for _, option := range options { - option(&massifOptions) - } - - return massifOptions -} diff --git a/logverification/app/massifoptions.go b/logverification/app/massifoptions.go deleted file mode 100644 index 90e266a..0000000 --- a/logverification/app/massifoptions.go +++ /dev/null @@ -1,56 +0,0 @@ -package app - -type MassifOptions struct { - - // NonLeafNode is an optional suppression - // - // of errors that occur due to attempting to get - // a massif based on a non leaf node mmrIndex. - NonLeafNode bool - - // TenantId is an optional tenant ID to use instead - // of the TenantId found on the eventJson. - TenantId string - - // MassifHeight is an optional massif height for the massif - // instead of the default. - MassifHeight uint8 -} - -type MassifOption func(*MassifOptions) - -// WithNonLeafNode is an optional suppression -// -// of errors that occur due to attempting to get -// a massif based on a non leaf node mmrIndex. -func WithNonLeafNode(nonLeafNode bool) MassifOption { - return func(mo *MassifOptions) { mo.NonLeafNode = nonLeafNode } -} - -// WithMassifTenantId is an optional tenant ID to use instead -// -// of the tenantId found on the eventJson. -func WithMassifTenantId(tenantId string) MassifOption { - return func(mo *MassifOptions) { mo.TenantId = tenantId } -} - -// WithMassifHeight is an optional massif height for the massif -// -// instead of the default. -func WithMassifHeight(massifHeight uint8) MassifOption { - return func(mo *MassifOptions) { mo.MassifHeight = massifHeight } -} - -// ParseMassifOptions parses the given options into a MassifOptions struct -func ParseMassifOptions(options ...MassifOption) MassifOptions { - massifOptions := MassifOptions{ - NonLeafNode: false, // default to erroring on non leaf nodes - MassifHeight: DefaultMassifHeight, // set the default massif height first - } - - for _, option := range options { - option(&massifOptions) - } - - return massifOptions -} diff --git a/logverification/verifylist.go b/logverification/verifylist.go index 1289ea4..be1a353 100644 --- a/logverification/verifylist.go +++ b/logverification/verifylist.go @@ -344,7 +344,7 @@ func VerifyAppEntryInList( return Unknown, err } - mmrEntry, err := appEntry.MMREntry(app.WithMassifContext(massifContext)) + mmrEntry, err := appEntry.MMREntry(massifContext) if err != nil { return Unknown, err }