package layoutbundleownerverificationv1

import (
	"bytes"
	"encoding/hex"
	"encoding/json"
	"io"
	"math"
	"reflect"
	"strconv"
	"testing"

	"github.com/pingcap-inc/nexuscrm-contract/pkg/layoutbundlekeyv1"
)

func TestImmutableConformanceVectors(t *testing.T) {
	var document receiptVectorDocument
	decoder := json.NewDecoder(bytes.NewReader(ConformanceVectorsJSON()))
	decoder.DisallowUnknownFields()
	if err := decoder.Decode(&document); err != nil {
		t.Fatal(err)
	}
	if err := decoder.Decode(&struct{}{}); err != io.EOF {
		t.Fatalf("unexpected trailing JSON: %v", err)
	}
	if document.SchemaVersion != "nexuscrm.layout-bundle-owner-verification-receipt.conformance/v1" {
		t.Fatalf("schema_version = %q", document.SchemaVersion)
	}
	if len(document.ReceiptVectors) != 3 ||
		len(document.SetVectors) != 2 ||
		len(document.WriterGenerationBoundaryVectors) != 3 ||
		len(document.ReceiptCountBoundaryVectors) != 2 ||
		len(document.RejectionVectors) != 6 {
		t.Fatalf(
			"vector counts = %d/%d/%d/%d/%d",
			len(document.ReceiptVectors),
			len(document.SetVectors),
			len(document.WriterGenerationBoundaryVectors),
			len(document.ReceiptCountBoundaryVectors),
			len(document.RejectionVectors),
		)
	}

	receiptsByName := map[string]Receipt{}
	ownerKinds := map[layoutbundlekeyv1.SlotOwnerKind]bool{}
	for _, vector := range document.ReceiptVectors {
		if vector.Name == "" {
			t.Fatal("receipt vector has a blank name")
		}
		if _, duplicate := receiptsByName[vector.Name]; duplicate {
			t.Fatalf("duplicate receipt vector %q", vector.Name)
		}
		receipt := vector.Receipt.receipt(t)
		receiptsByName[vector.Name] = receipt
		ownerKinds[receipt.BundleKey.SlotOwnerKind] = true
		t.Run("receipt/"+vector.Name, func(t *testing.T) {
			assertReceiptVectorIdentity(
				t,
				receipt,
				vector.CanonicalBytesLength,
				vector.CanonicalBytesHex,
				vector.ReceiptDigest,
			)
		})
	}
	if !reflect.DeepEqual(ownerKinds, map[layoutbundlekeyv1.SlotOwnerKind]bool{
		layoutbundlekeyv1.SlotOwnerKindApp:    true,
		layoutbundlekeyv1.SlotOwnerKindTenant: true,
		layoutbundlekeyv1.SlotOwnerKindSystem: true,
	}) {
		t.Fatalf("owner-kind vector coverage = %v", ownerKinds)
	}

	setsByName := map[string]receiptVectorSetValue{}
	for _, vector := range document.SetVectors {
		if vector.Name == "" {
			t.Fatal("set vector has a blank name")
		}
		if _, duplicate := setsByName[vector.Name]; duplicate {
			t.Fatalf("duplicate set vector %q", vector.Name)
		}
		setsByName[vector.Name] = vector
		t.Run("set/"+vector.Name, func(t *testing.T) {
			set, required := vector.values(t)
			if set.RequiredBundleKeySetDigest != vector.RequiredBundleKeySetDigest {
				t.Fatalf("set required digest = %s, vector = %s", set.RequiredBundleKeySetDigest, vector.RequiredBundleKeySetDigest)
			}
			receiptDigests, err := CanonicalReceiptDigests(set, required)
			if err != nil {
				t.Fatal(err)
			}
			if !reflect.DeepEqual(receiptDigests, vector.CanonicalReceiptDigests) {
				t.Fatalf("canonical singular receipt digests = %v, want %v", receiptDigests, vector.CanonicalReceiptDigests)
			}
			assertReceiptSetVectorIdentity(
				t,
				set,
				required,
				vector.CanonicalBytesLength,
				vector.CanonicalBytesHex,
				vector.ReceiptSetDigest,
			)
		})
	}
	for _, required := range []string{"empty-complete-set", "mixed-owner-permuted"} {
		if _, present := setsByName[required]; !present {
			t.Fatalf("required set vector %q missing", required)
		}
	}

	for _, vector := range document.WriterGenerationBoundaryVectors {
		t.Run(vector.Name, func(t *testing.T) {
			base, present := receiptsByName[vector.BaseReceiptVector]
			if !present {
				t.Fatalf("unknown base receipt vector %q", vector.BaseReceiptVector)
			}
			base.WriterReservationGeneration = receiptVectorUint64(t, "writer_reservation_generation", vector.WriterReservationGeneration)
			canonical, err := CanonicalReceiptBytes(base)
			if err != nil {
				t.Fatal(err)
			}
			if got := hex.EncodeToString(receiptGenerationEncoding(t, canonical)); got != vector.CanonicalULEB128Hex {
				t.Fatalf("generation encoding = %s, want %s", got, vector.CanonicalULEB128Hex)
			}
			assertReceiptVectorIdentity(t, base, vector.CanonicalBytesLength, "", vector.ReceiptDigest)
		})
	}

	for _, vector := range document.ReceiptCountBoundaryVectors {
		t.Run(vector.Name, func(t *testing.T) {
			if vector.SourceEnvelope != "the mixed-owner-permuted envelope" ||
				vector.SlotOwnerKind != string(layoutbundlekeyv1.SlotOwnerKindTenant) ||
				vector.SlotOwnerNamespace != "io.example.tenant" ||
				vector.LocalComponentKeyAlgorithm != "key256: followed by the lowercase hexadecimal index left-padded to 64 digits" ||
				vector.ReceiptInputOrder != "ascending index" ||
				vector.RequiredBundleKeyInputOrder != "descending index" ||
				vector.EvidenceVersion != TenantAuthorityEvidenceVersion ||
				vector.EvidenceDigest != receiptTestDigest('2') ||
				vector.VerificationState != 1 {
				t.Fatalf("count recipe %q changed: %#v", vector.Name, vector)
			}
			set, required := receiptCountSet(t, vector.ReceiptCount)
			if set.RequiredBundleKeySetDigest != vector.RequiredBundleKeySetDigest {
				t.Fatalf("required digest = %s, want %s", set.RequiredBundleKeySetDigest, vector.RequiredBundleKeySetDigest)
			}
			canonical, err := CanonicalReceiptSetBytes(set, required)
			if err != nil {
				t.Fatal(err)
			}
			if got := hex.EncodeToString(receiptCountEncoding(t, canonical)); got != vector.CanonicalULEB128Hex {
				t.Fatalf("count encoding = %s, want %s", got, vector.CanonicalULEB128Hex)
			}
			assertReceiptSetVectorIdentity(
				t,
				set,
				required,
				vector.CanonicalBytesLength,
				"",
				vector.ReceiptSetDigest,
			)
		})
	}

	mixed := setsByName["mixed-owner-permuted"]
	for _, vector := range document.RejectionVectors {
		t.Run("reject/"+vector.Name, func(t *testing.T) {
			if vector.BaseFixture != "mixed-owner-permuted" {
				t.Fatalf("base fixture = %q", vector.BaseFixture)
			}
			set, required := mixed.values(t)
			applyReceiptRejectionVector(t, &set, vector.Name)
			assertReceiptSetErrorContains(t, set, required, vector.ErrorContains)
			if vector.Mutation == "" {
				t.Fatal("mutation description is blank")
			}
		})
	}

	if document.MaximumCountRecipe.MaximumReceipts != MaxReceipts ||
		document.MaximumCountRecipe.OverflowReceipts != MaxReceipts+1 ||
		document.MaximumCountRecipe.OverflowErrorContains != "exceeds 100000 entries" {
		t.Fatalf("maximum-count recipe changed: %#v", document.MaximumCountRecipe)
	}

	assertExactSizeBoundaryVector(t, document.ExactSizeBoundaryRecipe)
}

func TestConformanceVectorsJSONReturnsDefensiveCopy(t *testing.T) {
	first := ConformanceVectorsJSON()
	if len(first) == 0 {
		t.Fatal("embedded vectors are empty")
	}
	first[0] ^= 0xff
	if bytes.Equal(first, ConformanceVectorsJSON()) {
		t.Fatal("ConformanceVectorsJSON returned shared mutable storage")
	}
}

func assertReceiptVectorIdentity(
	t *testing.T,
	receipt Receipt,
	canonicalLength string,
	canonicalHex string,
	wantDigest string,
) {
	t.Helper()
	canonical, err := CanonicalReceiptBytes(receipt)
	if err != nil {
		t.Fatal(err)
	}
	if want := receiptVectorUint64(t, "canonical_bytes_length", canonicalLength); uint64(len(canonical)) != want {
		t.Fatalf("canonical bytes length = %d, want %d", len(canonical), want)
	}
	if canonicalHex != "" {
		want, err := hex.DecodeString(canonicalHex)
		if err != nil {
			t.Fatalf("canonical_bytes_hex: %v", err)
		}
		if !bytes.Equal(canonical, want) {
			t.Fatalf("canonical bytes = %s, want %s", hex.EncodeToString(canonical), canonicalHex)
		}
	}
	digest, err := ReceiptDigest(receipt)
	if err != nil {
		t.Fatal(err)
	}
	if digest != wantDigest {
		t.Fatalf("receipt digest = %s, want %s", digest, wantDigest)
	}
}

func assertReceiptSetVectorIdentity(
	t *testing.T,
	set ReceiptSet,
	required layoutbundlekeyv1.RequiredBundleKeySet,
	canonicalLength string,
	canonicalHex string,
	wantDigest string,
) {
	t.Helper()
	canonical, err := CanonicalReceiptSetBytes(set, required)
	if err != nil {
		t.Fatal(err)
	}
	if want := receiptVectorUint64(t, "canonical_bytes_length", canonicalLength); uint64(len(canonical)) != want {
		t.Fatalf("canonical bytes length = %d, want %d", len(canonical), want)
	}
	if canonicalHex != "" {
		want, err := hex.DecodeString(canonicalHex)
		if err != nil {
			t.Fatalf("canonical_bytes_hex: %v", err)
		}
		if !bytes.Equal(canonical, want) {
			t.Fatalf("canonical bytes = %s, want %s", hex.EncodeToString(canonical), canonicalHex)
		}
	}
	digest, err := ReceiptSetDigest(set, required)
	if err != nil {
		t.Fatal(err)
	}
	if digest != wantDigest {
		t.Fatalf("receipt-set digest = %s, want %s", digest, wantDigest)
	}
}

func applyReceiptRejectionVector(t *testing.T, set *ReceiptSet, name string) {
	t.Helper()
	set.Receipts = append([]ReceiptEntry{}, set.Receipts...)
	switch name {
	case "unknown-verification-state":
		set.Receipts[0].VerificationState = 0x02
	case "duplicate-bundle-key":
		set.Receipts[1].BundleKey = set.Receipts[0].BundleKey
	case "missing-required-key":
		set.Receipts = set.Receipts[:len(set.Receipts)-1]
	case "extra-required-key":
		set.Receipts[0] = ReceiptEntry{
			BundleKey: layoutbundlekeyv1.BundleKey{
				SlotOwnerKind:      layoutbundlekeyv1.SlotOwnerKindTenant,
				SlotOwnerNamespace: "io.example.extra",
				LocalComponentKey:  receiptTestLocalKey('e'),
			},
			EvidenceVersion:   TenantAuthorityEvidenceVersion,
			EvidenceDigest:    receiptTestDigest('e'),
			VerificationState: VerificationStateVerified,
		}
	case "source-required-set-mismatch":
		set.RequiredBundleKeySetDigest = receiptTestDigest('f')
	case "foreign-evidence-version":
		set.Receipts[0].EvidenceVersion = AppAuthorityEvidenceVersion
	default:
		t.Fatalf("unknown rejection vector %q", name)
	}
}

func assertExactSizeBoundaryVector(t *testing.T, recipe receiptSizeBoundaryRecipe) {
	t.Helper()
	if recipe.Name != "reachable-31-mib-boundary" ||
		recipe.ReceiptSetVersionUTF8Bytes != 56 ||
		recipe.ReceiptSetVersionFramedBytes != 57 ||
		recipe.ReceiptVersionUTF8Bytes != 52 ||
		recipe.ReceiptVersionFramedBytes != 53 ||
		recipe.OrgID != "255 lowercase ASCII o bytes" ||
		recipe.OrgIDUTF8Bytes != 255 ||
		recipe.OrgIDFramedBytes != 257 ||
		recipe.WriterCommandID != "ffffffff-ffff-7fff-bfff-ffffffffffff" ||
		receiptVectorUint64(t, "writer_reservation_generation", recipe.WriterReservationGeneration) != math.MaxUint64 ||
		recipe.WriterCommandIDFramedBytes != 37 ||
		recipe.WriterReservationGenerationFramedBytes != 10 ||
		recipe.SourceRequestDigest != receiptTestDigest('a') ||
		recipe.SourceRequestDigestFramedBytes != 72 ||
		recipe.RequiredBundleKeySetDigestFramedBytes != 72 ||
		recipe.BundleKeyVersionFramedBytes != 30 ||
		recipe.ReceiptCount != MaxReceipts ||
		recipe.ReceiptCountFramedBytes != 3 ||
		recipe.SharedPrefixCanonicalBytes != 591 ||
		recipe.OwnerKind != string(layoutbundlekeyv1.SlotOwnerKindTenant) ||
		recipe.OwnerKindCanonicalByte != "02" ||
		recipe.NamespaceAlgorithm != "strings.Repeat(\"a\", 57) + fmt.Sprintf(\"%06x\", index) + \".\" + strings.Repeat(\"b\", namespace_bytes - 64)" ||
		recipe.Namespace126ByteReceiptCount != 94_735 ||
		recipe.Namespace126ByteEntryCanonicalBytes != 325 ||
		recipe.Namespace127ByteReceiptCount != 5_265 ||
		recipe.Namespace127ByteEntryCanonicalBytes != 326 ||
		recipe.LocalComponentKey != string(receiptTestLocalKey('1')) ||
		recipe.EvidenceVersion != TenantAuthorityEvidenceVersion ||
		recipe.EvidenceDigest != receiptTestDigest('2') ||
		recipe.VerificationState != 1 ||
		recipe.TotalCanonicalBytes != MaxCanonicalReceiptSetBytes ||
		recipe.OverflowMutation != "replace index 0 126-byte namespace with its 127-byte form" ||
		recipe.OverflowCanonicalBytes != MaxCanonicalReceiptSetBytes+1 {
		t.Fatalf("size-boundary recipe changed: %#v", recipe)
	}
	if recipe.Namespace126ByteReceiptCount+recipe.Namespace127ByteReceiptCount != MaxReceipts {
		t.Fatalf("recipe receipt count is incomplete")
	}
	if recipe.SharedPrefixCanonicalBytes+
		recipe.Namespace126ByteReceiptCount*recipe.Namespace126ByteEntryCanonicalBytes+
		recipe.Namespace127ByteReceiptCount*recipe.Namespace127ByteEntryCanonicalBytes != MaxCanonicalReceiptSetBytes {
		t.Fatal("recipe size formula does not reach the exact ceiling")
	}

	set, required := exactSizeBoundaryReceiptSet(t)
	if set.RequiredBundleKeySetDigest != recipe.RequiredBundleKeySetDigest {
		t.Fatalf("boundary required digest = %s, want %s", set.RequiredBundleKeySetDigest, recipe.RequiredBundleKeySetDigest)
	}
	digest, err := ReceiptSetDigest(set, required)
	if err != nil {
		t.Fatal(err)
	}
	if digest != recipe.ReceiptSetDigest {
		t.Fatalf("boundary set digest = %s, want %s", digest, recipe.ReceiptSetDigest)
	}
}

func receiptVectorUint64(t *testing.T, field, value string) uint64 {
	t.Helper()
	parsed, err := strconv.ParseUint(value, 10, 64)
	if err != nil {
		t.Fatalf("%s %q is not uint64: %v", field, value, err)
	}
	return parsed
}

type receiptVectorDocument struct {
	SchemaVersion                   string                           `json:"schema_version"`
	ReceiptVectors                  []receiptVectorValue             `json:"receipt_vectors"`
	SetVectors                      []receiptVectorSetValue          `json:"set_vectors"`
	WriterGenerationBoundaryVectors []receiptGenerationBoundaryValue `json:"writer_generation_boundary_vectors"`
	ReceiptCountBoundaryVectors     []receiptCountBoundaryValue      `json:"receipt_count_boundary_vectors"`
	RejectionVectors                []receiptRejectionVector         `json:"rejection_vectors"`
	MaximumCountRecipe              receiptMaximumCountRecipe        `json:"maximum_count_recipe"`
	ExactSizeBoundaryRecipe         receiptSizeBoundaryRecipe        `json:"exact_size_boundary_recipe"`
}

type receiptVectorValue struct {
	Name                 string               `json:"name"`
	Receipt              receiptVectorReceipt `json:"receipt"`
	CanonicalBytesLength string               `json:"canonical_bytes_length"`
	CanonicalBytesHex    string               `json:"canonical_bytes_hex"`
	ReceiptDigest        string               `json:"receipt_digest"`
}

type receiptVectorReceipt struct {
	ReceiptVersion              string                 `json:"receipt_version"`
	OrgID                       string                 `json:"org_id"`
	WriterCommandID             string                 `json:"writer_command_id"`
	WriterReservationGeneration string                 `json:"writer_reservation_generation"`
	SourceRequestDigest         string                 `json:"source_request_digest"`
	RequiredBundleKeySetDigest  string                 `json:"required_bundle_key_set_digest"`
	BundleKey                   receiptVectorBundleKey `json:"bundle_key"`
	EvidenceVersion             string                 `json:"evidence_version"`
	EvidenceDigest              string                 `json:"evidence_digest"`
	VerificationState           byte                   `json:"verification_state"`
}

func (value receiptVectorReceipt) receipt(t *testing.T) Receipt {
	t.Helper()
	return Receipt{
		ReceiptVersion:              value.ReceiptVersion,
		OrgID:                       value.OrgID,
		WriterCommandID:             value.WriterCommandID,
		WriterReservationGeneration: receiptVectorUint64(t, "writer_reservation_generation", value.WriterReservationGeneration),
		SourceRequestDigest:         value.SourceRequestDigest,
		RequiredBundleKeySetDigest:  value.RequiredBundleKeySetDigest,
		BundleKey:                   value.BundleKey.key(),
		EvidenceVersion:             value.EvidenceVersion,
		EvidenceDigest:              value.EvidenceDigest,
		VerificationState:           VerificationState(value.VerificationState),
	}
}

type receiptVectorBundleKey struct {
	SlotOwnerKind      string `json:"slot_owner_kind"`
	SlotOwnerNamespace string `json:"slot_owner_namespace"`
	LocalComponentKey  string `json:"local_component_key"`
}

func (value receiptVectorBundleKey) key() layoutbundlekeyv1.BundleKey {
	return layoutbundlekeyv1.BundleKey{
		SlotOwnerKind:      layoutbundlekeyv1.SlotOwnerKind(value.SlotOwnerKind),
		SlotOwnerNamespace: value.SlotOwnerNamespace,
		LocalComponentKey:  layoutbundlekeyv1.LocalComponentKey(value.LocalComponentKey),
	}
}

type receiptVectorSetValue struct {
	Name                       string                      `json:"name"`
	Fixture                    string                      `json:"fixture"`
	SourceEnvelope             receiptVectorSourceEnvelope `json:"source_envelope"`
	RequiredBundleKeySet       receiptVectorRequiredSet    `json:"required_bundle_key_set"`
	Receipts                   []receiptVectorEntry        `json:"receipts"`
	RequiredBundleKeySetDigest string                      `json:"required_bundle_key_set_digest"`
	CanonicalReceiptDigests    []string                    `json:"canonical_receipt_digests"`
	CanonicalBytesLength       string                      `json:"canonical_bytes_length"`
	CanonicalBytesHex          string                      `json:"canonical_bytes_hex"`
	ReceiptSetDigest           string                      `json:"receipt_set_digest"`
}

func (value receiptVectorSetValue) values(t *testing.T) (ReceiptSet, layoutbundlekeyv1.RequiredBundleKeySet) {
	t.Helper()
	required := layoutbundlekeyv1.RequiredBundleKeySet{
		Version:    value.RequiredBundleKeySet.Version,
		BundleKeys: make([]layoutbundlekeyv1.BundleKey, len(value.RequiredBundleKeySet.BundleKeys)),
	}
	for index, key := range value.RequiredBundleKeySet.BundleKeys {
		required.BundleKeys[index] = key.key()
	}
	entries := make([]ReceiptEntry, len(value.Receipts))
	for index, entry := range value.Receipts {
		entries[index] = ReceiptEntry{
			BundleKey:         entry.BundleKey.key(),
			EvidenceVersion:   entry.EvidenceVersion,
			EvidenceDigest:    entry.EvidenceDigest,
			VerificationState: VerificationState(entry.VerificationState),
		}
	}
	return ReceiptSet{
		ReceiptSetVersion:           value.SourceEnvelope.ReceiptSetVersion,
		ReceiptVersion:              value.SourceEnvelope.ReceiptVersion,
		OrgID:                       value.SourceEnvelope.OrgID,
		WriterCommandID:             value.SourceEnvelope.WriterCommandID,
		WriterReservationGeneration: receiptVectorUint64(t, "writer_reservation_generation", value.SourceEnvelope.WriterReservationGeneration),
		SourceRequestDigest:         value.SourceEnvelope.SourceRequestDigest,
		RequiredBundleKeySetDigest:  value.RequiredBundleKeySetDigest,
		Receipts:                    entries,
	}, required
}

type receiptVectorSourceEnvelope struct {
	ReceiptSetVersion           string `json:"receipt_set_version"`
	ReceiptVersion              string `json:"receipt_version"`
	OrgID                       string `json:"org_id"`
	WriterCommandID             string `json:"writer_command_id"`
	WriterReservationGeneration string `json:"writer_reservation_generation"`
	SourceRequestDigest         string `json:"source_request_digest"`
}

type receiptVectorRequiredSet struct {
	Version    string                   `json:"version"`
	BundleKeys []receiptVectorBundleKey `json:"bundle_keys"`
}

type receiptVectorEntry struct {
	BundleKey         receiptVectorBundleKey `json:"bundle_key"`
	EvidenceVersion   string                 `json:"evidence_version"`
	EvidenceDigest    string                 `json:"evidence_digest"`
	VerificationState byte                   `json:"verification_state"`
}

type receiptGenerationBoundaryValue struct {
	Name                        string `json:"name"`
	BaseReceiptVector           string `json:"base_receipt_vector"`
	WriterReservationGeneration string `json:"writer_reservation_generation"`
	CanonicalULEB128Hex         string `json:"canonical_u_leb128_hex"`
	CanonicalBytesLength        string `json:"canonical_bytes_length"`
	ReceiptDigest               string `json:"receipt_digest"`
}

type receiptCountBoundaryValue struct {
	Name                        string `json:"name"`
	SourceEnvelope              string `json:"source_envelope"`
	SlotOwnerKind               string `json:"slot_owner_kind"`
	SlotOwnerNamespace          string `json:"slot_owner_namespace"`
	LocalComponentKeyAlgorithm  string `json:"local_component_key_algorithm"`
	ReceiptInputOrder           string `json:"receipt_input_order"`
	RequiredBundleKeyInputOrder string `json:"required_bundle_key_input_order"`
	EvidenceVersion             string `json:"evidence_version"`
	EvidenceDigest              string `json:"evidence_digest"`
	VerificationState           byte   `json:"verification_state"`
	ReceiptCount                int    `json:"receipt_count"`
	CanonicalULEB128Hex         string `json:"canonical_u_leb128_hex"`
	RequiredBundleKeySetDigest  string `json:"required_bundle_key_set_digest"`
	CanonicalBytesLength        string `json:"canonical_bytes_length"`
	ReceiptSetDigest            string `json:"receipt_set_digest"`
}

type receiptRejectionVector struct {
	Name          string `json:"name"`
	BaseFixture   string `json:"base_fixture"`
	Mutation      string `json:"mutation"`
	ErrorContains string `json:"error_contains"`
}

type receiptMaximumCountRecipe struct {
	MaximumReceipts       int    `json:"maximum_receipts"`
	OverflowReceipts      int    `json:"overflow_receipts"`
	OverflowErrorContains string `json:"overflow_error_contains"`
}

type receiptSizeBoundaryRecipe struct {
	Name                                   string `json:"name"`
	ReceiptSetVersionUTF8Bytes             int    `json:"receipt_set_version_utf8_bytes"`
	ReceiptSetVersionFramedBytes           int    `json:"receipt_set_version_framed_bytes"`
	ReceiptVersionUTF8Bytes                int    `json:"receipt_version_utf8_bytes"`
	ReceiptVersionFramedBytes              int    `json:"receipt_version_framed_bytes"`
	OrgID                                  string `json:"org_id"`
	OrgIDUTF8Bytes                         int    `json:"org_id_utf8_bytes"`
	OrgIDFramedBytes                       int    `json:"org_id_framed_bytes"`
	WriterCommandID                        string `json:"writer_command_id"`
	WriterCommandIDFramedBytes             int    `json:"writer_command_id_framed_bytes"`
	WriterReservationGeneration            string `json:"writer_reservation_generation"`
	WriterReservationGenerationFramedBytes int    `json:"writer_reservation_generation_framed_bytes"`
	SourceRequestDigest                    string `json:"source_request_digest"`
	SourceRequestDigestFramedBytes         int    `json:"source_request_digest_framed_bytes"`
	RequiredBundleKeySetDigest             string `json:"required_bundle_key_set_digest"`
	RequiredBundleKeySetDigestFramedBytes  int    `json:"required_bundle_key_set_digest_framed_bytes"`
	BundleKeyVersionFramedBytes            int    `json:"bundle_key_version_framed_bytes"`
	ReceiptCount                           int    `json:"receipt_count"`
	ReceiptCountFramedBytes                int    `json:"receipt_count_framed_bytes"`
	SharedPrefixCanonicalBytes             int    `json:"shared_prefix_canonical_bytes"`
	OwnerKind                              string `json:"owner_kind"`
	OwnerKindCanonicalByte                 string `json:"owner_kind_canonical_byte"`
	NamespaceAlgorithm                     string `json:"namespace_algorithm"`
	Namespace126ByteReceiptCount           int    `json:"namespace_126_byte_receipt_count"`
	Namespace126ByteEntryCanonicalBytes    int    `json:"namespace_126_byte_entry_canonical_bytes"`
	Namespace127ByteReceiptCount           int    `json:"namespace_127_byte_receipt_count"`
	Namespace127ByteEntryCanonicalBytes    int    `json:"namespace_127_byte_entry_canonical_bytes"`
	LocalComponentKey                      string `json:"local_component_key"`
	EvidenceVersion                        string `json:"evidence_version"`
	EvidenceDigest                         string `json:"evidence_digest"`
	VerificationState                      byte   `json:"verification_state"`
	TotalCanonicalBytes                    int    `json:"total_canonical_bytes"`
	ReceiptSetDigest                       string `json:"receipt_set_digest"`
	OverflowMutation                       string `json:"overflow_mutation"`
	OverflowCanonicalBytes                 int    `json:"overflow_canonical_bytes"`
}
