From c3bae9bc37dc3daef6b454ea3e91d7272a2ca13b Mon Sep 17 00:00:00 2001 From: Henry Jewell Date: Thu, 6 Jun 2024 16:07:58 +0100 Subject: [PATCH 1/2] update to use the logverification module remove the copy stored in demos and update references re AB#9586 --- completeness/go.mod | 2 +- completeness/go.sum | 4 +- completeness/main.go | 2 +- logverification/consts.go | 8 - logverification/consts_test.go | 51 ---- logverification/eventhasher.go | 10 - logverification/eventhelpers.go | 82 ------ logverification/go.mod | 62 ----- logverification/go.sum | 194 -------------- logverification/leafrange.go | 25 -- logverification/logversion0.go | 55 ---- logverification/logversion0_test.go | 44 ---- logverification/massif.go | 123 --------- logverification/massifoptions.go | 56 ---- logverification/merklelogentry.go | 81 ------ logverification/proof.go | 74 ------ logverification/seal.go | 73 ------ logverification/verifyconsistency.go | 126 --------- logverification/verifyevent.go | 30 --- logverification/verifylist.go | 377 --------------------------- logverification/verifyoptions.go | 28 -- 21 files changed, 4 insertions(+), 1503 deletions(-) delete mode 100644 logverification/consts.go delete mode 100644 logverification/consts_test.go delete mode 100644 logverification/eventhasher.go delete mode 100644 logverification/eventhelpers.go delete mode 100644 logverification/go.mod delete mode 100644 logverification/go.sum delete mode 100644 logverification/leafrange.go delete mode 100644 logverification/logversion0.go delete mode 100644 logverification/logversion0_test.go delete mode 100644 logverification/massif.go delete mode 100644 logverification/massifoptions.go delete mode 100644 logverification/merklelogentry.go delete mode 100644 logverification/proof.go delete mode 100644 logverification/seal.go delete mode 100644 logverification/verifyconsistency.go delete mode 100644 logverification/verifyevent.go delete mode 100644 logverification/verifylist.go delete mode 100644 logverification/verifyoptions.go diff --git a/completeness/go.mod b/completeness/go.mod index 99f5e14..60c9ea4 100644 --- a/completeness/go.mod +++ b/completeness/go.mod @@ -4,7 +4,7 @@ go 1.22 require ( github.com/datatrails/go-datatrails-common v0.16.1 - github.com/datatrails/go-datatrails-demos/logverification v0.0.3 + github.com/datatrails/go-datatrails-logverification v0.1.2 github.com/stretchr/testify v1.9.0 ) diff --git a/completeness/go.sum b/completeness/go.sum index 36afbd3..79ca1e8 100644 --- a/completeness/go.sum +++ b/completeness/go.sum @@ -45,8 +45,8 @@ github.com/datatrails/go-datatrails-common v0.16.1 h1:kaNOwyu8EmBbIR44daWDiUZxBt github.com/datatrails/go-datatrails-common v0.16.1/go.mod h1:IEcuwUaFl+bI1tt30r+Ov2+nvpcAZH/kXmAPGFjkwT4= github.com/datatrails/go-datatrails-common-api-gen v0.4.8 h1:IzrhGHi9TyEASjk06QjsayjtpXYCKuDt78+ffLuOCNM= github.com/datatrails/go-datatrails-common-api-gen v0.4.8/go.mod h1:zlwFPJXYAK7yqgLtxKUgkF5gw9ddxoqWS+Ruhf+Ksw0= -github.com/datatrails/go-datatrails-demos/logverification v0.0.3 h1:P8DU8ZSVqOmMkm37LWhxpWXrBPwhExuGSXpJ+306LyE= -github.com/datatrails/go-datatrails-demos/logverification v0.0.3/go.mod h1:5uMSYrfH8l3RNtiu934BXhwym9TorhSp375O188MJrM= +github.com/datatrails/go-datatrails-logverification v0.1.2 h1:VohfbxpYzbV6nrW2JerUqy7bElyl0oR78ZXY8g80YYI= +github.com/datatrails/go-datatrails-logverification v0.1.2/go.mod h1:0n2sTXhR9LUT5w3+KxqXGMs5XIVRa7Ip2RJ6QgCWpVY= github.com/datatrails/go-datatrails-merklelog/massifs v0.0.7 h1:844V2QxLhVmSkOISu00qHMxs4+XpGU2tHQ433S3akHY= github.com/datatrails/go-datatrails-merklelog/massifs v0.0.7/go.mod h1:eNMW+ZfyGT4ttj/vAE56Ut1uWfdc9zW1W7yIIl2XF1k= github.com/datatrails/go-datatrails-merklelog/mmr v0.0.1 h1:XggMVejsJ72cAL/msjPhQUSQNeElSh/O1zZcvX4d4JU= diff --git a/completeness/main.go b/completeness/main.go index 91352b5..e679b08 100644 --- a/completeness/main.go +++ b/completeness/main.go @@ -6,7 +6,7 @@ import ( "strings" "github.com/datatrails/go-datatrails-common/azblob" - "github.com/datatrails/go-datatrails-demos/logverification" + "github.com/datatrails/go-datatrails-logverification/logverification" ) /** diff --git a/logverification/consts.go b/logverification/consts.go deleted file mode 100644 index fd90d6b..0000000 --- a/logverification/consts.go +++ /dev/null @@ -1,8 +0,0 @@ -package logverification - -const ( - DefaultMassifHeight = 14 - - // LeafTypePlain is the domain separator for events - LeafTypePlain = uint8(0) -) diff --git a/logverification/consts_test.go b/logverification/consts_test.go deleted file mode 100644 index 1802d9b..0000000 --- a/logverification/consts_test.go +++ /dev/null @@ -1,51 +0,0 @@ -package logverification - -/** - * Defines constants only used in testing. - */ - -const ( - testEventJson = ` - { - "identity": "assets/9ccdc19b-44a1-434c-afab-14f8eac3405c/events/82c9f5c2-fe77-4885-86aa-417f654d3b2f", - "asset_identity": "assets/9ccdc19b-44a1-434c-afab-14f8eac3405c", - "event_attributes": { - "1": "pour flour and milk into bowl", - "2": "mix together until gloopy", - "3": "slowly add in the sugar while still mixing", - "4": "finally add in the eggs", - "5": "put in the over until golden brown" - }, - "asset_attributes": {}, - "operation": "Record", - "behaviour": "RecordEvidence", - "timestamp_declared": "2024-01-24T11:42:16Z", - "timestamp_accepted": "2024-01-24T11:42:16Z", - "timestamp_committed": "2024-01-24T11:42:17.121Z", - "principal_declared": { - "issuer": "cupcake-world", - "subject": "chris the cupcake connoisseur", - "display_name": "chris", - "email": "chris@example.com" - }, - "principal_accepted": { - "issuer": "https://app.dev-user-0.dev.datatrails.ai/appidpv1", - "subject": "924c9054-c342-47a3-a7b8-8c0bfedd37a3", - "display_name": "API", - "email": "" - }, - "confirmation_status": "COMMITTED", - "transaction_id": "", - "block_number": 0, - "transaction_index": 0, - "from": "0xc98130dc7b292FB485F842785f6F63A520a404A5", - "tenant_identity": "tenant/15c551cf-40ed-4cdb-a94b-142d6e3c620a", - "merklelog_entry": { - "commit": { - "index": 53, - "idtimestamp": "0x018d3b472e22146400" - } - } - } - ` -) diff --git a/logverification/eventhasher.go b/logverification/eventhasher.go deleted file mode 100644 index ff9a816..0000000 --- a/logverification/eventhasher.go +++ /dev/null @@ -1,10 +0,0 @@ -package logverification - -/** - * Event Hasher defines an interface that reproduces a hash of a datatrails event - * that is present on the merkle log. - */ - -type EventHasher interface { - HashEvent(eventJson []byte) ([]byte, error) -} diff --git a/logverification/eventhelpers.go b/logverification/eventhelpers.go deleted file mode 100644 index 8394b70..0000000 --- a/logverification/eventhelpers.go +++ /dev/null @@ -1,82 +0,0 @@ -package logverification - -import ( - "encoding/json" - "sort" - - "github.com/datatrails/go-datatrails-common-api-gen/assets/v2/assets" - "google.golang.org/protobuf/encoding/protojson" -) - -// EventDetails contains key information for verifying inclusion of merkle log events -type EventDetails struct { - EventID string - TenantID string - EventHash []byte - MerkleLog *assets.MerkleLogEntry -} - -// ParseEventList takes a json list of events returned by the datatrails events API -// -// and returns an mmrIndex ascending, sorted list of golang list of event details whose members are easier to access. -func ParseEventList(eventsJson []byte) ([]EventDetails, 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 := []EventDetails{} - for _, eventJson := range eventListJson.Events { - - // 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 - } - - hasher := LogVersion0Hasher{} - eventHash, err := hasher.HashEvent(eventJson) - if err != nil { - return nil, err - } - - eventDetails := EventDetails{ - EventID: entry.Identity, - TenantID: entry.TenantIdentity, - EventHash: eventHash, - MerkleLog: merkleLog, - } - events = append(events, eventDetails) - } - - // 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].MerkleLog.Commit.Index < events[j].MerkleLog.Commit.Index - }) - - return events, nil - -} diff --git a/logverification/go.mod b/logverification/go.mod deleted file mode 100644 index 2764319..0000000 --- a/logverification/go.mod +++ /dev/null @@ -1,62 +0,0 @@ -module github.com/datatrails/go-datatrails-demos/logverification - -go 1.22 - -require ( - github.com/datatrails/go-datatrails-common v0.16.1 - github.com/datatrails/go-datatrails-common-api-gen v0.4.5 - github.com/datatrails/go-datatrails-merklelog/massifs v0.0.7 - github.com/datatrails/go-datatrails-merklelog/mmr v0.0.1 - github.com/datatrails/go-datatrails-simplehash v0.0.3 - github.com/stretchr/testify v1.9.0 - google.golang.org/protobuf v1.34.1 -) - -require ( - github.com/Azure/azure-sdk-for-go v68.0.0+incompatible // indirect - github.com/Azure/azure-sdk-for-go/sdk/azcore v1.11.1 // indirect - github.com/Azure/azure-sdk-for-go/sdk/internal v1.8.0 // indirect - github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus v1.7.0 // indirect - github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v0.4.1 // indirect - github.com/Azure/go-amqp v1.0.5 // indirect - github.com/Azure/go-autorest v14.2.0+incompatible // indirect - github.com/Azure/go-autorest/autorest v0.11.29 // indirect - github.com/Azure/go-autorest/autorest/adal v0.9.23 // indirect - github.com/Azure/go-autorest/autorest/azure/auth v0.5.12 // indirect - github.com/Azure/go-autorest/autorest/azure/cli v0.4.6 // indirect - github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect - github.com/Azure/go-autorest/autorest/to v0.4.0 // indirect - github.com/Azure/go-autorest/autorest/validation v0.3.1 // indirect - github.com/Azure/go-autorest/logger v0.2.1 // indirect - github.com/Azure/go-autorest/tracing v0.6.0 // indirect - github.com/datatrails/go-datatrails-merklelog/mmrtesting v0.0.1 // indirect - github.com/davecgh/go-spew v1.1.1 // indirect - github.com/dimchansky/utfbom v1.1.1 // indirect - github.com/envoyproxy/protoc-gen-validate v1.0.4 // indirect - github.com/fxamacker/cbor/v2 v2.6.0 // indirect - github.com/gabriel-vasile/mimetype v1.4.3 // indirect - github.com/golang-jwt/jwt/v4 v4.5.0 // indirect - github.com/google/uuid v1.6.0 // indirect - github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1 // indirect - github.com/ldclabs/cose/go v0.0.0-20221214142927-d22c1cfc2154 // indirect - github.com/mitchellh/go-homedir v1.1.0 // indirect - github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492 // indirect - github.com/opentracing-contrib/go-stdlib v1.0.0 // indirect - github.com/opentracing/opentracing-go v1.2.0 // indirect - github.com/openzipkin-contrib/zipkin-go-opentracing v0.5.0 // indirect - github.com/openzipkin/zipkin-go v0.4.3 // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/veraison/go-cose v1.1.0 // indirect - github.com/x448/float16 v0.8.4 // indirect - 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.23.0 // indirect - golang.org/x/net v0.25.0 // indirect - golang.org/x/sys v0.20.0 // indirect - golang.org/x/text v0.15.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20240513163218-0867130af1f8 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240513163218-0867130af1f8 // indirect - google.golang.org/grpc v1.64.0 // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect -) diff --git a/logverification/go.sum b/logverification/go.sum deleted file mode 100644 index 1cc0814..0000000 --- a/logverification/go.sum +++ /dev/null @@ -1,194 +0,0 @@ -github.com/Azure/azure-sdk-for-go v68.0.0+incompatible h1:fcYLmCpyNYRnvJbPerq7U0hS+6+I79yEDJBqVNcqUzU= -github.com/Azure/azure-sdk-for-go v68.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.11.1 h1:E+OJmp2tPvt1W+amx48v1eqbjDYsgN+RzP4q16yV5eM= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.11.1/go.mod h1:a6xsAQUZg+VsS3TJ05SRp524Hs4pZ/AeFSr5ENf0Yjo= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.5.1 h1:sO0/P7g68FrryJzljemN+6GTssUXdANk6aJ7T1ZxnsQ= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.5.1/go.mod h1:h8hyGFDsU5HMivxiS2iYFZsgDbU9OnnJ163x5UGVKYo= -github.com/Azure/azure-sdk-for-go/sdk/internal v1.8.0 h1:jBQA3cKT4L2rWMpgE7Yt3Hwh2aUj8KXjIGLxjHeYNNo= -github.com/Azure/azure-sdk-for-go/sdk/internal v1.8.0/go.mod h1:4OG6tQ9EOP/MT0NMjDlRzWoVFxfu9rN9B2X+tlSVktg= -github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus v1.7.0 h1:QISzMrspEvZj4zrrN2wlNwfum5RmnKQhQNiSujwH7oU= -github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus v1.7.0/go.mod h1:xNjFERdhyMqZncbNJSPBsTCddk5kwsUVUzELQPMj/LA= -github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v0.4.1 h1:QSdcrd/UFJv6Bp/CfoVf2SrENpFn9P6Yh8yb+xNhYMM= -github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v0.4.1/go.mod h1:eZ4g6GUvXiGulfIbbhh1Xr4XwUYaYaWMqzGD/284wCA= -github.com/Azure/go-amqp v1.0.5 h1:po5+ljlcNSU8xtapHTe8gIc8yHxCzC03E8afH2g1ftU= -github.com/Azure/go-amqp v1.0.5/go.mod h1:vZAogwdrkbyK3Mla8m/CxSc/aKdnTZ4IbPxl51Y5WZE= -github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs= -github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= -github.com/Azure/go-autorest/autorest v0.11.24/go.mod h1:G6kyRlFnTuSbEYkQGawPfsCswgme4iYf6rfSKUDzbCc= -github.com/Azure/go-autorest/autorest v0.11.29 h1:I4+HL/JDvErx2LjyzaVxllw2lRDB5/BT2Bm4g20iqYw= -github.com/Azure/go-autorest/autorest v0.11.29/go.mod h1:ZtEzC4Jy2JDrZLxvWs8LrBWEBycl1hbT1eknI8MtfAs= -github.com/Azure/go-autorest/autorest/adal v0.9.18/go.mod h1:XVVeme+LZwABT8K5Lc3hA4nAe8LDBVle26gTrguhhPQ= -github.com/Azure/go-autorest/autorest/adal v0.9.22/go.mod h1:XuAbAEUv2Tta//+voMI038TrJBqjKam0me7qR+L8Cmk= -github.com/Azure/go-autorest/autorest/adal v0.9.23 h1:Yepx8CvFxwNKpH6ja7RZ+sKX+DWYNldbLiALMC3BTz8= -github.com/Azure/go-autorest/autorest/adal v0.9.23/go.mod h1:5pcMqFkdPhviJdlEy3kC/v1ZLnQl0MH6XA5YCcMhy4c= -github.com/Azure/go-autorest/autorest/azure/auth v0.5.12 h1:wkAZRgT/pn8HhFyzfe9UnqOjJYqlembgCTi72Bm/xKk= -github.com/Azure/go-autorest/autorest/azure/auth v0.5.12/go.mod h1:84w/uV8E37feW2NCJ08uT9VBfjfUHpgLVnG2InYD6cg= -github.com/Azure/go-autorest/autorest/azure/cli v0.4.5/go.mod h1:ADQAXrkgm7acgWVUNamOgh8YNrv4p27l3Wc55oVfpzg= -github.com/Azure/go-autorest/autorest/azure/cli v0.4.6 h1:w77/uPk80ZET2F+AfQExZyEWtn+0Rk/uw17m9fv5Ajc= -github.com/Azure/go-autorest/autorest/azure/cli v0.4.6/go.mod h1:piCfgPho7BiIDdEQ1+g4VmKyD5y+p/XtSNqE6Hc4QD0= -github.com/Azure/go-autorest/autorest/date v0.3.0 h1:7gUk1U5M/CQbp9WoqinNzJar+8KY+LPI6wiWrP/myHw= -github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74= -github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= -github.com/Azure/go-autorest/autorest/mocks v0.4.2 h1:PGN4EDXnuQbojHbU0UWoNvmu9AGVwYHG9/fkDYhtAfw= -github.com/Azure/go-autorest/autorest/mocks v0.4.2/go.mod h1:Vy7OitM9Kei0i1Oj+LvyAWMXJHeKH1MVlzFugfVrmyU= -github.com/Azure/go-autorest/autorest/to v0.4.0 h1:oXVqrxakqqV1UZdSazDOPOLvOIz+XA683u8EctwboHk= -github.com/Azure/go-autorest/autorest/to v0.4.0/go.mod h1:fE8iZBn7LQR7zH/9XU2NcPR4o9jEImooCeWJcYV/zLE= -github.com/Azure/go-autorest/autorest/validation v0.3.1 h1:AgyqjAd94fwNAoTjl/WQXg4VvFeRFpO+UhNyRXqF1ac= -github.com/Azure/go-autorest/autorest/validation v0.3.1/go.mod h1:yhLgjC0Wda5DYXl6JAsWyUe4KVNffhoDhG0zVzUMo3E= -github.com/Azure/go-autorest/logger v0.2.1 h1:IG7i4p/mDa2Ce4TRyAO8IHnVhAVF3RFU+ZtXWSmf4Tg= -github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= -github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo= -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.16.1 h1:kaNOwyu8EmBbIR44daWDiUZxBtersV4s/s73CUEvHyU= -github.com/datatrails/go-datatrails-common v0.16.1/go.mod h1:IEcuwUaFl+bI1tt30r+Ov2+nvpcAZH/kXmAPGFjkwT4= -github.com/datatrails/go-datatrails-common-api-gen v0.4.5 h1:QtxIFSdOEf6bhHZd7g/MfWdCWfPEtwTQNDz3K9u33+c= -github.com/datatrails/go-datatrails-common-api-gen v0.4.5/go.mod h1:OQN91xvlW6xcWTFvwsM2Nn4PZwFAIOE52FG7yRl4QPQ= -github.com/datatrails/go-datatrails-merklelog/massifs v0.0.7 h1:844V2QxLhVmSkOISu00qHMxs4+XpGU2tHQ433S3akHY= -github.com/datatrails/go-datatrails-merklelog/massifs v0.0.7/go.mod h1:eNMW+ZfyGT4ttj/vAE56Ut1uWfdc9zW1W7yIIl2XF1k= -github.com/datatrails/go-datatrails-merklelog/mmr v0.0.1 h1:XggMVejsJ72cAL/msjPhQUSQNeElSh/O1zZcvX4d4JU= -github.com/datatrails/go-datatrails-merklelog/mmr v0.0.1/go.mod h1:+Oz8O6bns0rF6gr03xJzKTBzUzyskZ8Gics8/qeNzYk= -github.com/datatrails/go-datatrails-merklelog/mmrtesting v0.0.1 h1:sIyXWKTadqmVEsPj66RlKwRKzNQ7hK9SH1fRjZFDCa8= -github.com/datatrails/go-datatrails-merklelog/mmrtesting v0.0.1/go.mod h1:KGdkOtamWG48EN4AXtTHPv6C0jJKrj840IMSkrD+egk= -github.com/datatrails/go-datatrails-simplehash v0.0.3 h1:H4zNsdB9d2KMZ3EqM6n6AMGYB/RquEjANqcNrUlZtp8= -github.com/datatrails/go-datatrails-simplehash v0.0.3/go.mod h1:ML1qlHH+SeaSTphpKw9psCsdI4UaTH3d68GpWOWOKgg= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dimchansky/utfbom v1.1.1 h1:vV6w1AhK4VMnhBno/TPVCoK9U/LP0PkLCS9tbxHdi/U= -github.com/dimchansky/utfbom v1.1.1/go.mod h1:SxdoEBH5qIqFocHMyGOXVAybYJdr71b1Q/j0mACtrfE= -github.com/envoyproxy/protoc-gen-validate v1.0.4 h1:gVPz/FMfvh57HdSJQyvBtF00j8JU4zdyUgIUNhlgg0A= -github.com/envoyproxy/protoc-gen-validate v1.0.4/go.mod h1:qys6tmnRsYrQqIhm2bvKZH4Blx/1gTIZ2UKVY1M+Yew= -github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= -github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= -github.com/fxamacker/cbor/v2 v2.6.0 h1:sU6J2usfADwWlYDAFhZBQ6TnLFBHxgesMrQfQgk1tWA= -github.com/fxamacker/cbor/v2 v2.6.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= -github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0= -github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk= -github.com/golang-jwt/jwt v3.2.1+incompatible h1:73Z+4BJcrTC+KczS6WvTPvRGOp1WmfEP4Q1lOd9Z/+c= -github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= -github.com/golang-jwt/jwt/v4 v4.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= -github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= -github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= -github.com/golang-jwt/jwt/v5 v5.2.0 h1:d/ix8ftRUorsN+5eMIlF4T6J8CAt9rch3My2winC1Jw= -github.com/golang-jwt/jwt/v5 v5.2.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= -github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= -github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= -github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= -github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= -github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= -github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= -github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1 h1:/c3QmbOGMGTOumP2iT/rCwB7b0QDGLKzqOmktBjT+Is= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1/go.mod h1:5SN9VR2LTsRFsrEC6FHgRbTWrTHu6tqPeKxEQv15giM= -github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= -github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= -github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= -github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= -github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= -github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= -github.com/ldclabs/cose/go v0.0.0-20221214142927-d22c1cfc2154 h1:+ANMOp3EbA4WEKS/jZi3jlyoNMFMDeq0+dXFxMdOwBc= -github.com/ldclabs/cose/go v0.0.0-20221214142927-d22c1cfc2154/go.mod h1:ItUTr90SrkBAvLf5UsxqN+lMfF1rw21mEcFa28XqOzQ= -github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= -github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492 h1:lM6RxxfUMrYL/f8bWEUqdXrANWtrL7Nndbm9iFN0DlU= -github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis= -github.com/opentracing-contrib/go-stdlib v1.0.0 h1:TBS7YuVotp8myLon4Pv7BtCBzOTo1DeZCld0Z63mW2w= -github.com/opentracing-contrib/go-stdlib v1.0.0/go.mod h1:qtI1ogk+2JhVPIXVc6q+NHziSmy2W5GbdQZFUHADCBU= -github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= -github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= -github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= -github.com/openzipkin-contrib/zipkin-go-opentracing v0.5.0 h1:uhcF5Jd7rP9DVEL10Siffyepr6SvlKbUsjH5JpNCRi8= -github.com/openzipkin-contrib/zipkin-go-opentracing v0.5.0/go.mod h1:+oCZ5GXXr7KPI/DNOQORPTq5AWHfALJj9c72b0+YsEY= -github.com/openzipkin/zipkin-go v0.4.3 h1:9EGwpqkgnwdEIJ+Od7QVSEIH+ocmm5nPat0G7sjsSdg= -github.com/openzipkin/zipkin-go v0.4.3/go.mod h1:M9wCJZFWCo2RiY+o1eBCEMe0Dp2S5LDHcMZmk3RmK7c= -github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ= -github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= -github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -github.com/veraison/go-cose v1.1.0 h1:AalPS4VGiKavpAzIlBjrn7bhqXiXi4jbMYY/2+UC+4o= -github.com/veraison/go-cose v1.1.0/go.mod h1:7ziE85vSq4ScFTg6wyoMXjucIGOf4JkFEZi/an96Ct4= -github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= -github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= -github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -github.com/zeebo/bencode v1.0.0 h1:zgop0Wu1nu4IexAZeCZ5qbsjU4O1vMrfCrVgUjbHVuA= -github.com/zeebo/bencode v1.0.0/go.mod h1:Ct7CkrWIQuLWAy9M3atFHYq4kG9Ao/SsY5cdtCXmp9Y= -go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= -go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= -go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= -go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= -go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -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.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI= -golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -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.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= -golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= -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/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= -golang.org/x/sys v0.20.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= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -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.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk= -golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -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/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/genproto/googleapis/api v0.0.0-20240513163218-0867130af1f8 h1:W5Xj/70xIA4x60O/IFyXivR5MGqblAb8R3w26pnD6No= -google.golang.org/genproto/googleapis/api v0.0.0-20240513163218-0867130af1f8/go.mod h1:vPrPUTsDCYxXWjP7clS81mZ6/803D8K4iM9Ma27VKas= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240513163218-0867130af1f8 h1:mxSlqyb8ZAHsYDCfiXN1EDdNTdvjUJSLY+OnAUtYNYA= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240513163218-0867130af1f8/go.mod h1:I7Y+G38R2bu5j1aLzfFmQfTcU/WnFuqDwLZAbvKTKpM= -google.golang.org/grpc v1.64.0 h1:KH3VH9y/MgNQg1dE7b3XfVK0GsPSIzJwdF617gUSbvY= -google.golang.org/grpc v1.64.0/go.mod h1:oxjF8E3FBnjp+/gVFYdWacaLDx9na1aqy9oovLpxQYg= -google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg= -google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU= -gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU= -nhooyr.io/websocket v1.8.10 h1:mv4p+MnGrLDcPlBoWsvPP7XCzTYMXP9F9eIGoKbgx7Q= -nhooyr.io/websocket v1.8.10/go.mod h1:rN9OFWIUwuxg4fR5tELlYC04bXYowCP9GX47ivo2l+c= diff --git a/logverification/leafrange.go b/logverification/leafrange.go deleted file mode 100644 index 8ca6637..0000000 --- a/logverification/leafrange.go +++ /dev/null @@ -1,25 +0,0 @@ -package logverification - -import "github.com/datatrails/go-datatrails-merklelog/mmr" - -/** - * Leaf Range holds utilities for finding the range of leaves in the merkle log to - * consider for a list of events. - */ - -// LeafRange gets the range of leaf indexes for a given list of -// -// 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 []EventDetails) (uint64, uint64) { - - lowerBoundMMRIndex := sortedEvents[0].MerkleLog.Commit.Index - lowerBoundLeafIndex := mmr.LeafCount(lowerBoundMMRIndex+1) - 1 // Note: LeafCount takes an mmrIndex here not a size - - upperBoundMMRIndex := sortedEvents[len(sortedEvents)-1].MerkleLog.Commit.Index - upperBoundLeafIndex := mmr.LeafCount(upperBoundMMRIndex+1) - 1 // Note: LeafCount takes an mmrIndex here not a size - - return lowerBoundLeafIndex, upperBoundLeafIndex - -} diff --git a/logverification/logversion0.go b/logverification/logversion0.go deleted file mode 100644 index 9e5e973..0000000 --- a/logverification/logversion0.go +++ /dev/null @@ -1,55 +0,0 @@ -package logverification - -import ( - "github.com/datatrails/go-datatrails-merklelog/massifs" - "github.com/datatrails/go-datatrails-simplehash/simplehash" -) - -/** - * Log Version 0 defines the hashing schema used to generate the hash, used - * as a value, of a merkle log node. - */ - -type LogVersion0Hasher struct { -} - -func NewLogVersion0Hasher() *LogVersion0Hasher { - return &LogVersion0Hasher{} -} - -// HashEvent defines the hashing schema for log version 0 nodes, -// given the event data in json format. -// -// The hashing schema is as follows: -// -// hash(domain separator + id timestamp + simplehashv3(eventJson)) -// -// Where: -// - 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) { - merkleLogEntry, err := MerklelogEntry(eventJson) - if err != nil { - return nil, err - } - - simplehashv3Hasher := simplehash.NewHasherV3() - - // the idCommitted is in hex from the event, we need to convert it to uint64 - idCommitted, _, err := massifs.SplitIDTimestampHex(merkleLogEntry.Commit.Idtimestamp) - if err != nil { - return nil, err - } - - err = simplehashv3Hasher.HashEventFromJSON( - eventJson, - simplehash.WithPrefix([]byte{LeafTypePlain}), - simplehash.WithIDCommitted(idCommitted)) - - if err != nil { - return nil, err - } - - return simplehashv3Hasher.Sum(nil), nil -} diff --git a/logverification/logversion0_test.go b/logverification/logversion0_test.go deleted file mode 100644 index d2af207..0000000 --- a/logverification/logversion0_test.go +++ /dev/null @@ -1,44 +0,0 @@ -package logverification - -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/massif.go b/logverification/massif.go deleted file mode 100644 index 9772e14..0000000 --- a/logverification/massif.go +++ /dev/null @@ -1,123 +0,0 @@ -package logverification - -import ( - "context" - "errors" - "time" - - "github.com/datatrails/go-datatrails-common/azblob" - "github.com/datatrails/go-datatrails-common/logger" - "github.com/datatrails/go-datatrails-merklelog/massifs" -) - -const ( - contextTimeout = 30 * time.Second -) - -var ( - ErrNilMassifContext = errors.New("nil massif context") -) - -// Massif gets the massif (blob) that contains the given mmrIndex, from azure blob storage -// -// defined by the azblob configuration. -func Massif(mmrIndex uint64, massifReader massifs.MassifReader, tenantId string, massifHeight uint8, opts ...MassifOption) (*massifs.MassifContext, error) { - - massifOptions := ParseMassifOptions(opts...) - - massifIndex, err := massifs.MassifIndexFromMMRIndex(massifHeight, mmrIndex) - - // we don't want to suppress NotLeaf error for mmrIndex that are not leaf - // nodes, so just surface any error. - if !massifOptions.nonLeafNode && err != nil { - return nil, err - } - - // we want to suppress NotLeaf error for mmrIndexs that are not leaf - // nodes. - if massifOptions.nonLeafNode && !errors.Is(err, massifs.ErrNotleaf) { - return nil, err - } - - ctx, cancel := context.WithTimeout(context.Background(), contextTimeout) - defer cancel() - - massif, err := massifReader.GetMassif(ctx, tenantId, massifIndex) - if err != nil { - return nil, err - } - - return &massif, nil -} - -// MassifFromEvent gets the massif (blob) that contains the given event, from azure blob storage -// -// defined by the azblob configuration. -func MassifFromEvent(eventJson []byte, reader azblob.Reader, options ...MassifOption) (*massifs.MassifContext, error) { - - massifOptions := ParseMassifOptions(options...) - - // 1. get the massif (blob) index from the merkleLogEntry on the event - merkleLogEntry, err := MerklelogEntry(eventJson) - if err != nil { - return nil, err - } - - massifHeight := massifOptions.massifHeight - - // if tenant ID is not supplied - // we should find it based on the given eventJson - tenantId := massifOptions.tenantId - if tenantId == "" { - tenantId, err = TenantIdentity(eventJson) - if err != nil { - return nil, err - } - } - - massifReader := massifs.NewMassifReader(logger.Sugar, reader) - - return Massif(merkleLogEntry.Commit.Index, massifReader, tenantId, massifHeight) -} - -// 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 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. -// -// A Massif is a blob that contains a portion of the merkle log. -// A MassifContext is the context used to get specific massifs. -func UpdateMassifContext(massifReader massifs.MassifReader, massifContext *massifs.MassifContext, mmrIndex uint64, tenantID string, massifHeight uint8) error { - - // there is a chance here that massifContext is nil, in this case we can't do anything - // as we set the massifContext as a side effect, and there is no pointer value. - if massifContext == nil { - return ErrNilMassifContext - } - - // check if the current massifContext contains the given mmrIndex - if mmrIndex >= massifContext.Start.FirstIndex && mmrIndex < massifContext.LastLeafMMRIndex() { - return nil - } - - // if we get here, we know that we need a different massifContext to the given massifContext - - nextContext, err := Massif(mmrIndex, massifReader, tenantID, massifHeight) - if err != nil { - return err - } - - *massifContext = *nextContext - return nil -} diff --git a/logverification/massifoptions.go b/logverification/massifoptions.go deleted file mode 100644 index e1941b1..0000000 --- a/logverification/massifoptions.go +++ /dev/null @@ -1,56 +0,0 @@ -package logverification - -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/merklelogentry.go b/logverification/merklelogentry.go deleted file mode 100644 index d2869b5..0000000 --- a/logverification/merklelogentry.go +++ /dev/null @@ -1,81 +0,0 @@ -package logverification - -import ( - "encoding/json" - "errors" - - "github.com/datatrails/go-datatrails-common-api-gen/assets/v2/assets" - "google.golang.org/protobuf/encoding/protojson" -) - -// MerklelogEntry safely decode the event json from the api and recovers the merkle log entry field -func MerklelogEntry(eventJson []byte) (*assets.MerkleLogEntry, error) { - - // Special care is needed because the protobuf to json conversion represents - // uint64's as strings. And those do not round trip using a mix of generated - // types and the generic json decoder. - // - // The pb -> json marshalsc a string encoded value. Then the decode to the - // generated go lang type fails, because the generated type has uint64 and - // the marshaled content is a string. The solution is to use the protojson - // library rather than the generic json library. But this requires the - // destination type be a protobuf generated type. - // - // That on its own solves the problem if the decoding of the MerklelogEntry - // is defered via a custome type. Here, additionaly, we make use of a - // generated type which accepts the structure of a datatrails event as it is - // seen over the api surfiace. - // Note: see the completeness demo for a different approach to this issue - - eventResp := struct { - Identity string `json:"identity"` - MerkleLogEntry json.RawMessage `json:"merklelog_entry"` - }{} - - err := json.Unmarshal(eventJson, &eventResp) - if err != nil { - return nil, err - } - - merkleLogEntry := assets.MerkleLogEntry{} - err = protojson.Unmarshal(eventResp.MerkleLogEntry, &merkleLogEntry) - if err != nil { - return nil, err - } - - return &merkleLogEntry, nil -} - -// EventIdentity gets the event identity from the given event json -func EventIdentity(eventJson []byte) (string, error) { - - eventResp := map[string]any{} - err := json.Unmarshal(eventJson, &eventResp) - if err != nil { - return "", err - } - - identity, ok := eventResp["identity"].(string) - if !ok { - return "", errors.New("no identity found for event") - } - - return identity, nil -} - -// TenantIdentity gets the event's tenant identity from the given event json -func TenantIdentity(eventJson []byte) (string, error) { - - eventResp := map[string]any{} - err := json.Unmarshal(eventJson, &eventResp) - if err != nil { - return "", err - } - - tenantId, ok := eventResp["tenant_identity"].(string) - if !ok { - return "", errors.New("no tenant identity found for event") - } - - return tenantId, nil -} diff --git a/logverification/proof.go b/logverification/proof.go deleted file mode 100644 index 16f13d9..0000000 --- a/logverification/proof.go +++ /dev/null @@ -1,74 +0,0 @@ -package logverification - -import ( - "crypto/sha256" - - "github.com/datatrails/go-datatrails-merklelog/massifs" - "github.com/datatrails/go-datatrails-merklelog/mmr" -) - -/** - * Utility functions or generating a datatrails merkle log event proof and - * verifying that proof. - */ - -// EventProof gets the event proof for the given event and the given massif the event -// -// is contained in. -func EventProof(eventJson []byte, massif *massifs.MassifContext) ([][]byte, error) { - - // 1. get the massif (blob) index from the merkleLogEntry on the event - merkleLogEntry, err := MerklelogEntry(eventJson) - if err != nil { - return nil, err - } - - // 2. now generate the proof - hasher := sha256.New() - - // get the size of the complete tenant mmr - mmrSize := massif.RangeCount() - - proof, err := mmr.IndexProof(mmrSize, massif, hasher, merkleLogEntry.Commit.Index) - if err != nil { - return nil, err - } - - return proof, nil -} - -// VerifyProof verifies the given proof against the given event -func VerifyProof(eventJson []byte, proof [][]byte, massif *massifs.MassifContext) (bool, error) { - - // 1. get the massif (blob) index from the merkleLogEntry on the event - merkleLogEntry, err := MerklelogEntry(eventJson) - if err != nil { - return false, err - } - - // 2. get the event hash from the event json - hashSchema, err := ChooseHashingSchema(massif.Start) - if err != nil { - return false, err - } - - eventHash, err := hashSchema.HashEvent(eventJson) - if err != nil { - return false, err - } - - hasher := sha256.New() - - // 3. get the root of the mmr - mmrSize := massif.RangeCount() - - root, err := mmr.GetRoot(mmrSize, massif, hasher) - if err != nil { - return false, err - } - - // 4. attempt to verify the proof - verified := mmr.VerifyInclusion(mmrSize, hasher, eventHash, merkleLogEntry.Commit.Index, proof, root) - - return verified, nil -} diff --git a/logverification/seal.go b/logverification/seal.go deleted file mode 100644 index ea63b0c..0000000 --- a/logverification/seal.go +++ /dev/null @@ -1,73 +0,0 @@ -package logverification - -import ( - "context" - "fmt" - "hash" - - "github.com/datatrails/go-datatrails-common/azblob" - "github.com/datatrails/go-datatrails-common/cbor" - "github.com/datatrails/go-datatrails-common/cose" - "github.com/datatrails/go-datatrails-common/logger" - "github.com/datatrails/go-datatrails-merklelog/massifs" - "github.com/datatrails/go-datatrails-merklelog/mmr" -) - -/** - * log signed root (seal) utilities. - */ - -// SignedLogState gets the signed state of the log for the massif at the given massif Index. -func SignedLogState( - ctx context.Context, - reader azblob.Reader, - hasher hash.Hash, - codec cbor.CBORCodec, - tenantID string, - massifIndex uint64, -) (*cose.CoseSign1Message, error) { - - sealReader := massifs.NewSignedRootReader(logger.Sugar, reader, codec) - - // Fetch the signed and unsigned state of the log - // at the massif given the massif index. - signedState, logState, err := sealReader.GetLatestMassifSignedRoot(ctx, tenantID, uint32(massifIndex)) - if err != nil { - return nil, fmt.Errorf("SignedLogState failed: unable to get latest signed root: %w", err) - } - - massifReader := massifs.NewMassifReader(logger.Sugar, reader) - massifContext, err := massifReader.GetMassif(ctx, tenantID, massifIndex) - if err != nil { - return nil, fmt.Errorf("SignedLogState failed: unable to get massif from storage for massif index: %v, err: %w", - massifIndex, err) - } - - // The log state at time of sealing is the Payload. It included the root, but this is removed - // from the stored log state. This forces a verifier to recompute the merkle root from their view - // of the data. If verification succeeds when this computed root is added to signedStateNow, then - // we can be confident that DataTrails signed this state, and that the root matches your data. - logState.Root, err = mmr.GetRoot(logState.MMRSize, &massifContext, hasher) - if err != nil { - return nil, fmt.Errorf("SignedLogState failed: unable to get root for massifContextNow: %w", err) - } - - signedState.Payload, err = codec.MarshalCBOR(logState) - if err != nil { - return nil, fmt.Errorf("SignedLogState failed: unable to cbor encode log state: %w", err) - } - - return signedState, nil -} - -// LogState returns the unsigned state of the log, given a signed state. -func LogState(signedState *cose.CoseSign1Message, codec cbor.CBORCodec) (*massifs.MMRState, error) { - - unsignedState := &massifs.MMRState{} - err := codec.UnmarshalInto(signedState.Payload, unsignedState) - if err != nil { - return nil, err - } - - return unsignedState, nil -} diff --git a/logverification/verifyconsistency.go b/logverification/verifyconsistency.go deleted file mode 100644 index 0ef00af..0000000 --- a/logverification/verifyconsistency.go +++ /dev/null @@ -1,126 +0,0 @@ -package logverification - -import ( - "context" - "crypto/ecdsa" - "errors" - "fmt" - "hash" - - "github.com/datatrails/go-datatrails-common/azblob" - "github.com/datatrails/go-datatrails-common/logger" - "github.com/datatrails/go-datatrails-merklelog/massifs" - "github.com/datatrails/go-datatrails-merklelog/mmr" -) - -// VerifyConsistency takes two log states, and verifies that log state B is appended onto log state A -// -// NOTE: the log state's signatures are not verified in this function, it is expected that the signature verification -// is done as a separate step to the consistency verification. -// -// NOTE: it is expected that both logStateA and logStateB have had their root recalculated. -func VerifyConsistency( - ctx context.Context, - hasher hash.Hash, - reader azblob.Reader, - tenantID string, - logStateA *massifs.MMRState, - logStateB *massifs.MMRState, -) (bool, error) { - - if logStateA.Root == nil || logStateB.Root == nil { - return false, errors.New("VerifyConsistency failed: the roots for both log state A and log state B need to be set") - } - - if len(logStateA.Root) == 0 || len(logStateB.Root) == 0 { - return false, errors.New("VerifyConsistency failed: the roots for both log state A and log state B need to be set") - } - - massifReader := massifs.NewMassifReader(logger.Sugar, reader) - - // last massif in the merkle log for log state A - massifContextA, err := Massif(logStateA.MMRSize-1, massifReader, tenantID, DefaultMassifHeight, WithNonLeafNode(true)) - if err != nil { - return false, fmt.Errorf("VerifyConsistency failed: unable to get the last massif for log state A: %w", err) - } - - // last massif in the merkle log for log state B - massifContextB, err := Massif(logStateB.MMRSize-1, massifReader, tenantID, DefaultMassifHeight, WithNonLeafNode(true)) - if err != nil { - return false, fmt.Errorf("VerifyConsistency failed: unable to get the last massif for log state B: %w", err) - } - - // We construct a proof of consistency between logStateA and logStateB. - // This will be a proof that logStateB derives from logStateA. - consistencyProof, err := mmr.IndexConsistencyProof(logStateA.MMRSize, logStateB.MMRSize, massifContextB, hasher) - if err != nil { - return false, fmt.Errorf("VerifyConsistency failed: unable to generate consistency proof: %w", err) - } - - // In order to verify the proof we take the hashes of all of the peaks in logStateA. - // The hash of each of these peaks guarantees the integrity of all of its child nodes, so we - // don't need to check every hash. - - // Peaks returned as MMR positions (1-based), not MMR indices (0-based). The location of these - // is deterministic: Given an MMR of a particular size, the peaks will always be in the same place. - logPeaksA := mmr.Peaks(logStateA.MMRSize) - - // Get the hashes of all of the peaks. - logPeakHashesA, err := mmr.PeakBagRHS(massifContextA, hasher, 0, logPeaksA) - if err != nil { - return false, errors.New("error") - } - - // Lastly, verify the consistency proof using the peak hashes from our backed-up log. If this - // returns true, then we can confidently say that everything in the backed-up log is in the state - // of the log described by this signed state. - verified := mmr.VerifyConsistency(hasher, logPeakHashesA, consistencyProof, logStateA.Root, logStateB.Root) - return verified, nil -} - -// VerifyConsistencyFromMassifs takes a massif context providing access to data from the past, and a massif -// context providing access to the current version of the log. It returns whether or not the -// new version of the log is consistent with the previous version (i.e. it contains all of the -// same nodes in the same positions.) -func VerifyConsistencyFromMassifs( - ctx context.Context, - verificationKey ecdsa.PublicKey, - hasher hash.Hash, - blobReader azblob.Reader, - massifContextBefore *massifs.MassifContext, - massifContextNow *massifs.MassifContext, - logStateNow *massifs.MMRState, -) (bool, error) { - // Grab some core info about our backed up merkle log, which we'll need to prove consistency - mmrSizeBefore := massifContextBefore.Count() - rootBefore, err := mmr.GetRoot(mmrSizeBefore, massifContextBefore, hasher) - if err != nil { - return false, fmt.Errorf("VerifyConsistency failed: unable to get root for massifContextBefore: %w", err) - } - - // We construct a proof of consistency between the backed up MMR log and the head of the log. - consistencyProof, err := mmr.IndexConsistencyProof(mmrSizeBefore, logStateNow.MMRSize, massifContextNow, hasher) - if err != nil { - return false, errors.New("error") - } - - // In order to verify the proof we take the hashes of all of the peaks in the backed up log. - // The hash of each of these peaks guarantees the integrity of all of its child nodes, so we - // don't need to check every hash. - - // Peaks returned as MMR positions (1-based), not MMR indices (0-based). The location of these - // is deterministic: Given an MMR of a particular size, the peaks will always be in the same place. - backupLogPeaks := mmr.Peaks(mmrSizeBefore) - - // Get the hashes of all of the peaks. - backupLogPeakHashes, err := mmr.PeakBagRHS(massifContextNow, hasher, 0, backupLogPeaks) - if err != nil { - return false, errors.New("error") - } - - // Lastly, verify the consistency proof using the peak hashes from our backed-up log. If this - // returns true, then we can confidently say that everything in the backed-up log is in the state - // of the log described by this signed state. - verified := mmr.VerifyConsistency(hasher, backupLogPeakHashes, consistencyProof, rootBefore, logStateNow.Root) - return verified, nil -} diff --git a/logverification/verifyevent.go b/logverification/verifyevent.go deleted file mode 100644 index c375c4d..0000000 --- a/logverification/verifyevent.go +++ /dev/null @@ -1,30 +0,0 @@ -package logverification - -import ( - "github.com/datatrails/go-datatrails-common/azblob" -) - -/** - * Verifies a single datatrails event is present on the immutable merkle log. - */ - -// VerifyEvent verifies the integrity of the given event json -// -// against the immutable merkle log, aquired using the given reader. -// -// Returns true if the event is found to be on the log, otherwise false. -func VerifyEvent(reader azblob.Reader, eventJSON []byte, options ...MassifOption) (bool, error) { - - massif, err := MassifFromEvent(eventJSON, reader, options...) - - if err != nil { - return false, err - } - - proof, err := EventProof(eventJSON, massif) - if err != nil { - return false, err - } - - return VerifyProof(eventJSON, proof, massif) -} diff --git a/logverification/verifylist.go b/logverification/verifylist.go deleted file mode 100644 index 75c5bc0..0000000 --- a/logverification/verifylist.go +++ /dev/null @@ -1,377 +0,0 @@ -package logverification - -import ( - "bytes" - "crypto/sha256" - "errors" - "hash" - - "github.com/datatrails/go-datatrails-common/azblob" - "github.com/datatrails/go-datatrails-common/logger" - "github.com/datatrails/go-datatrails-merklelog/massifs" - "github.com/datatrails/go-datatrails-merklelog/mmr" -) - -/** - * Verifies that a list of events is also on the immutable audit log. - * - * Terms: - * - * Complete: - * A complete subset of a list that does not skip any elements in the original list - * greater than the start of the subset, and less than the end of the subset. - * - * In the below example, [2,3,4] is a complete subset of the list, - * whereas [2,4] is not, as it skips over 3. - * - * [1, 2, 3, 4, 5, 6] - * - * Leaf Range: - * A complete subset of leaves in the merklelog from lowest mmrIndex to highest mmrIndex. - * - * The boundaries of the range of leaves are determined by the lowest and largest mmrIndex on the given list of events. - * - * In the below example the event with the lowest mmrIndex matches leaf2 of the mmr, - * and the event with the largest mmrIndex matches leaf4 of the mmr: - * - * ↓ leaf range ↓ - * |-------------------------------| - * | leaf1 leaf2 leaf3 leaf4 leaf5 | - * |-------------------------------| - * - * - * Included Event: - * An event in the given list, that is included on the immutable log. - * - * Example of Included events: - * - * |----------------------| - * | event1 event2 event3 | event list (lowest mmrIndex to highest) - * |----------------------| - * ↓ ↓ ↓ - * |----------------------| - * | leaf1 leaf2 leaf3 | leaf range from merklelog - * |----------------------| - * - * Excluded Event: - * An event in the given list, that is not included on the immutable log. - * - * Example of Excluded event2: - * - * |-----------------------------| - * | event1 event2 event3 event4 | event list (lowest mmrIndex to highest) - * |-----------------------------| - * ↓ ↓ ↓ - * |-----------------------------| - * | leaf1 leaf2 leaf3 | leaf range from merklelog - * |-----------------------------| - * - * Omitted Event: - * An event on the immutable log, - * within the range of the list of events given, - * that is not included in the list of events given. - * - * Example of Omitted Event at leaf2: - * - * |-----------------------------| - * | event1 event3 event4 | event list (lowest mmrIndex to highest) - * |-----------------------------| - * ↓ ↓ ↓ - * |-----------------------------| - * | leaf1 leaf2 leaf3 leaf4 | leaf range from merklelog - * |-----------------------------| - */ - -type EventType int - -const ( - - // Unknown event is a given event that is unknown - Unknown EventType = iota - - // Included event is a given event that is included on the immutable log - Included - - // Excluded event is a given event that is NOT included on the immutable log - Excluded - - // Omitted is an event on the immutable log, that has not been given within an expected list of events. - Omitted -) - -var ( - ErrIntermediateNode = errors.New("event references an intermediate node on the merkle log") - ErrDuplicateEventMMRIndex = errors.New("event mmrIndex is the same as the previous event") - ErrEventNotOnLeaf = errors.New("event does not correspond to the event found on the leaf node") - ErrInclusionProofVerify = errors.New("event failed to verify the inclusion proof on the merkle log") - ErrNotEnoughEventsInList = errors.New("the number of events in the list is less than the number of leafs on the log") -) - -/** VerifyList verifies a given list of events against a range of leaves in the immutable merkle log. - * - * The list of events given is the json response from a datatrails list API call. - * - * The boundaries of the range of leaves are determined by the lowest and largest mmrIndex on the given list of events. - * In the below example the event with the lowest mmrIndex matches leaf2 of the mmr, - * and the event with the largest mmrIndex matches leaf4 of the mmr: - * - * ↓ leaf range ↓ - * |-------------------------------| - * | leaf1 leaf2 leaf3 leaf4 leaf5 | - * |-------------------------------| - * - * Once a range of leaves in the mmr has been established, we iterate over each leaf in the range - * and each event in the list (sorted lowest to highest by mmrIndex). - * - * We check that each event is INCLUDED in the mmr at the leaf index it is in tandem with - * in the iteration: - * - * |----------------------| - * | event1 event2 event3 | event list (lowest mmrIndex to highest) - * |----------------------| - * ↓ ↓ ↓ - * |----------------------| - * | leaf1 leaf2 leaf3 | leaf range from merklelog - * |----------------------| - * - * If every event within the list is included at its expected leaf index, we say the list is COMPLETE. - * - * If an event within the list of events is not present on the immutable merklelog - * at the expected leaf index it is in tandem with, we call that an EXCLUDED event. - * In the below example, event2 is an EXCLUDED event. (Note: proof of exclusion using the trie index is not shown in this demo) - * - * |-----------------------------| - * | event1 event2 event3 event4 | event list (lowest mmrIndex to highest) - * |-----------------------------| - * ↓ ↓ ↓ - * |-----------------------------| - * | leaf1 leaf2 leaf3 | leaf range from merklelog - * |-----------------------------| - * - * If there is a leaf within the range of leaves that does not have an event, within the list of events included, - * we call that an OMITTED event. - * - * In the below example the event included at leaf2 is an example of an ommitted event. - * - * |-----------------------------| - * | event1 event3 event4 | event list (lowest mmrIndex to highest) - * |-----------------------------| - * ↓ ↓ ↓ - * |-----------------------------| - * | leaf1 leaf2 leaf3 leaf4 | leaf range from merklelog - * |-----------------------------| - * - * Returns the omitted event mmrIndexes. - * - * The options argument can be the following: - * - * WithTenantId - the tenantId of the merklelog, the event is expected - * to be included on. E.g. the public tenant - * for public events. - */ -func VerifyList(reader azblob.Reader, eventListJson []byte, options ...VerifyOption) ([]uint64, error) { - - verifyOptions := ParseOptions(options...) - - hasher := sha256.New() - - massifContext := massifs.MassifContext{} - omittedMMRIndices := []uint64{} - - events, err := ParseEventList(eventListJson) - if err != nil { - return nil, err - } - - lowestLeafIndex, highestLeafIndex := LeafRange(events) - - massifReader := massifs.NewMassifReader(logger.Sugar, reader) - - eventIndex := 0 - - for leafIndex := lowestLeafIndex; leafIndex <= highestLeafIndex; leafIndex += 1 { - - if eventIndex >= len(events) { - return nil, ErrNotEnoughEventsInList - } - - event := events[eventIndex] - - // ensure we set the tenantId if - // if it passed in as an optional argument - tenantId := verifyOptions.tenantId - if tenantId == "" { - - // otherwise set it to the event tenantID - tenantId = event.TenantID - } - - eventType, err := VerifyEventInList(hasher, leafIndex, event, massifReader, &massifContext, tenantId) - if err != nil { - - // NOTE: for now fail at the first sign of an EXCLUDED event. - // If the event is EXCLUDED, we could log that like omitted and carry - // on with the next event in the list at the same leaf index. - return nil, err - } - - // if the event is OMITTED add the leaf to the omitted list - if eventType == Omitted { - omittedMMRIndices = append(omittedMMRIndices, mmr.TreeIndex(leafIndex)) - - // as the event is still the lowest mmrIndex we check this event - // against the next leaf - continue - } - - eventIndex += 1 - - } - - return omittedMMRIndices, nil -} - -// VerifyEventInList takes the next leaf in the list of leaves and the next event in the list of events -// -// and verifies that the event is in that leaf position. -func VerifyEventInList( - hasher hash.Hash, - leafIndex uint64, - event EventDetails, - reader massifs.MassifReader, - massifContext *massifs.MassifContext, - tenantID string, -) (EventType, error) { - - hasher.Reset() - - leafMMRIndex := mmr.TreeIndex(leafIndex) - eventMMRIndex := event.MerkleLog.Commit.Index - - // First we check if the event mmrIndex corresponds to a leaf node. - // - // ONLY leaf nodes correspond to events. - // - // Therefore if the event mmrIndex corresponds to an intermediate node, - // the event is not in the merkle log, it is EXCLUDED. - indexHeight := mmr.IndexHeight(eventMMRIndex) - - // all leaf nodes are at height 0 - if indexHeight != 0 { - return Excluded, ErrIntermediateNode - } - - // When the next event in the list of events has an mmrindex LESS THAN the next leaf in the range of leaves. - // - // This means the mmr index of the event matches the previous leaf node. - // - // This can occur because one of the following: - // 1. The event is a duplicate of the previous event in the list. - // 2. The event is not included on the previous leaf, but says it is. - // - // In both cases we say the event is not on the merkle log, it is EXCLUDED. - // - // Example: - // Event mmrIndex: 10 - // Leaf mmrIndex: 11 - // - // 14 - // / \ - // / \ - // / \ - // / \ - // 6 13 - // / \ / \ - // 2 5 9 12 17 - // / \ / \ / \ / \ / \ - // 0 1 3 4 7 8 10 11 15 16 <- Leaf Nodes - // - // NOTE: in the future we may mark a duplicated event as DUPLICATED instead of EXCLUDED. - // - // NOTE: we can make the above assumptions because: - // 1. the event mmrIndex is the next in the list of events, - // so the previous event was included on the previous leaf node. - // 2. we have already checked that the event mmrIndex is not an intermediate node. - if eventMMRIndex < leafMMRIndex { - return Excluded, ErrDuplicateEventMMRIndex - } - - // When the next event in the list of events has an mmrindex GREATER THAN the next leaf in the range of leaves. - // - // This means the mmr index of the event matches a future leaf node. - // - // This can occur because there are events on the merklelog that are not included in the list of events. - // The event at the leaf mmr index is an OMITTED event. - // - // - // Example: - // Event mmrIndex: 10 - // Leaf mmrIndex: 4 - // - // 14 - // / \ - // / \ - // / \ - // / \ - // 6 13 - // / \ / \ - // 2 5 9 12 17 - // / \ / \ / \ / \ / \ - // 0 1 3 4 7 8 10 11 15 16 <- Leaf Nodes - // - // NOTE: we can make the above assumptions because: - // 1. the event mmrIndex is the next in the list of events, - // so the previous event was included on the previous leaf node. - // 2. we have already checked that the event mmrIndex is not an intermediate node. - if eventMMRIndex > leafMMRIndex { - return Omitted, nil - } - - // If we reach this point, the next event in the list of events has an mmrindex EQUAL TO the next leaf in the range of leaves. - // - // We now do an inclusion proof on the event, to prove that the event is included at the leaf node. - - // Ensure we're using the correct massif for the current leaf - err := UpdateMassifContext(reader, massifContext, leafMMRIndex, tenantID, DefaultMassifHeight) - if err != nil { - return Unknown, err - } - - // Get the leaf node mmrEntry - leafMMREntry, err := massifContext.Get(leafMMRIndex) - if err != nil { - return Unknown, err - } - - // Check that the leaf node mmrEntry is the same as the event hash - // - // If its not, we know that the given event is not the same as the event on the leaf node. - if !bytes.Equal(leafMMREntry, event.EventHash) { - return Excluded, ErrEventNotOnLeaf - } - - // Now we know that the event is the event stored on the leaf node, - // we can do an inclusion proof of the leaf node on the merkle log. - mmrSize := massifContext.RangeCount() - root, err := mmr.GetRoot(mmrSize, massifContext, hasher) - if err != nil { - return Unknown, err - } - - inclusionProof, err := mmr.IndexProof(mmrSize, massifContext, hasher, leafMMRIndex) - if err != nil { - return Unknown, err - } - - verified := mmr.VerifyInclusion(mmrSize, hasher, event.EventHash, leafMMRIndex, inclusionProof, root) - - // if the inclusion proof verification failed, return EXCLUDED. - // - // This means the leaf node is not included on the merklelog. - if !verified { - return Excluded, ErrInclusionProofVerify - } - - return Included, nil - -} diff --git a/logverification/verifyoptions.go b/logverification/verifyoptions.go deleted file mode 100644 index 2aa6023..0000000 --- a/logverification/verifyoptions.go +++ /dev/null @@ -1,28 +0,0 @@ -package logverification - -type VerifyOptions struct { - - // tenantId is an optional tenant ID to use instead - // of the tenantId found on the eventJson. - tenantId string -} - -type VerifyOption func(*VerifyOptions) - -// WithTenantId is an optional tenant ID to use instead -// -// of the tenantId found on the eventJson. -func WithTenantId(tenantId string) VerifyOption { - return func(vo *VerifyOptions) { vo.tenantId = tenantId } -} - -// ParseOptions parses the given options into a VerifyOptions struct -func ParseOptions(options ...VerifyOption) VerifyOptions { - verifyOptions := VerifyOptions{} - - for _, option := range options { - option(&verifyOptions) - } - - return verifyOptions -} From b76c6855952604041f72c5dd40d4f36c12b8250f Mon Sep 17 00:00:00 2001 From: Henry Jewell Date: Thu, 6 Jun 2024 17:56:20 +0100 Subject: [PATCH 2/2] fixup! update to use the logverification module --- integrity/go.mod | 8 ++++---- integrity/go.sum | 4 ++-- integrity/main.go | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/integrity/go.mod b/integrity/go.mod index 54a316e..2a27a15 100644 --- a/integrity/go.mod +++ b/integrity/go.mod @@ -2,13 +2,13 @@ module github.com/datatrails/go-datatrails-demos/integrity go 1.22 +require github.com/datatrails/go-datatrails-common v0.16.1 + require ( - github.com/datatrails/go-datatrails-common v0.16.1 - github.com/datatrails/go-datatrails-demos/logverification v0.0.3 + github.com/datatrails/go-datatrails-logverification v0.1.2 + github.com/stretchr/testify v1.9.0 ) -require github.com/stretchr/testify v1.9.0 - require ( github.com/Azure/azure-sdk-for-go v68.0.0+incompatible // indirect github.com/Azure/azure-sdk-for-go/sdk/azcore v1.11.1 // indirect diff --git a/integrity/go.sum b/integrity/go.sum index 36afbd3..79ca1e8 100644 --- a/integrity/go.sum +++ b/integrity/go.sum @@ -45,8 +45,8 @@ github.com/datatrails/go-datatrails-common v0.16.1 h1:kaNOwyu8EmBbIR44daWDiUZxBt github.com/datatrails/go-datatrails-common v0.16.1/go.mod h1:IEcuwUaFl+bI1tt30r+Ov2+nvpcAZH/kXmAPGFjkwT4= github.com/datatrails/go-datatrails-common-api-gen v0.4.8 h1:IzrhGHi9TyEASjk06QjsayjtpXYCKuDt78+ffLuOCNM= github.com/datatrails/go-datatrails-common-api-gen v0.4.8/go.mod h1:zlwFPJXYAK7yqgLtxKUgkF5gw9ddxoqWS+Ruhf+Ksw0= -github.com/datatrails/go-datatrails-demos/logverification v0.0.3 h1:P8DU8ZSVqOmMkm37LWhxpWXrBPwhExuGSXpJ+306LyE= -github.com/datatrails/go-datatrails-demos/logverification v0.0.3/go.mod h1:5uMSYrfH8l3RNtiu934BXhwym9TorhSp375O188MJrM= +github.com/datatrails/go-datatrails-logverification v0.1.2 h1:VohfbxpYzbV6nrW2JerUqy7bElyl0oR78ZXY8g80YYI= +github.com/datatrails/go-datatrails-logverification v0.1.2/go.mod h1:0n2sTXhR9LUT5w3+KxqXGMs5XIVRa7Ip2RJ6QgCWpVY= github.com/datatrails/go-datatrails-merklelog/massifs v0.0.7 h1:844V2QxLhVmSkOISu00qHMxs4+XpGU2tHQ433S3akHY= github.com/datatrails/go-datatrails-merklelog/massifs v0.0.7/go.mod h1:eNMW+ZfyGT4ttj/vAE56Ut1uWfdc9zW1W7yIIl2XF1k= github.com/datatrails/go-datatrails-merklelog/mmr v0.0.1 h1:XggMVejsJ72cAL/msjPhQUSQNeElSh/O1zZcvX4d4JU= diff --git a/integrity/main.go b/integrity/main.go index 9758b96..2ebc173 100644 --- a/integrity/main.go +++ b/integrity/main.go @@ -5,7 +5,7 @@ import ( "strings" "github.com/datatrails/go-datatrails-common/azblob" - "github.com/datatrails/go-datatrails-demos/logverification" + "github.com/datatrails/go-datatrails-logverification/logverification" ) /** @@ -98,7 +98,7 @@ func IntegrityDemo(eventJson []byte) (verified bool, err error) { } // now verify the public event is in the merklelog - return logverification.VerifyEvent(reader, []byte(eventNoPublicPrefix), logverification.WithTenantId(publicTenantID)) + return logverification.VerifyEvent(reader, []byte(eventNoPublicPrefix), logverification.WithMassifTenantId(publicTenantID)) }