Skip to content

Reimplement Witness/WitnessGroup in terms of TLogPolicy - #1160

Merged
AlCutter merged 2 commits into
mainfrom
migrate_tlog_policy_1
Sep 10, 2026
Merged

Reimplement Witness/WitnessGroup in terms of TLogPolicy#1160
AlCutter merged 2 commits into
mainfrom
migrate_tlog_policy_1

Conversation

@AlCutter

@AlCutter AlCutter commented Sep 8, 2026

Copy link
Copy Markdown
Collaborator

This PR starts the process of migrating Tessera over to use the policy support implemented in github.com/transparency-dev/formats/policy.

The witness policy c'tors are re-implemented in TLogPolicy, and helper functions are provided to convert between the two representations.

Towards #1152

@AlCutter
AlCutter force-pushed the migrate_tlog_policy_1 branch from b87f5a4 to 595d099 Compare September 8, 2026 14:24
@AlCutter AlCutter changed the title migrate tlog policy 1 Reimplement Witness/WitnessGroup in terms of TLogPolicy Sep 8, 2026
@AlCutter
AlCutter force-pushed the migrate_tlog_policy_1 branch 2 times, most recently from d89a2a7 to fdafe41 Compare September 8, 2026 14:37
@AlCutter
AlCutter requested a review from roger2hk September 8, 2026 14:40
@AlCutter
AlCutter marked this pull request as ready for review September 8, 2026 14:40
@AlCutter
AlCutter requested a review from a team as a code owner September 8, 2026 14:40
Comment thread witness.go
return WitnessGroup{}, fmt.Errorf("invalid policy: member %q not defined", m)
}
}
wg := NewWitnessGroup(int(g.Threshold), members...)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The NewWitnessGroup(n, children...) panics if n < 0 || n > len(children). Do we need any verification here and return error?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I could add the check, but that would have had to have been an invalid policy which somehow made it through parsing to get to here, in which case panic is probably reasonable?

Comment thread witness_test.go Outdated
Comment on lines +740 to +741
w1 := Witness{vkey: vKey1, Key: v1}
w2 := Witness{vkey: vKey2, Key: v2}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use NewWitness as w1 and w2 are instantiated without setting witName.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Comment thread witness.go Outdated
alreadyAdded := false
for _, existing := range p.Witnesses {
if existing.Name == witName {
if existing.Verifier == c.Key && (existing.VKey == c.vkey || c.vkey == "") {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should the comparison be using the key identity (i.e. key name, key hash) instead of the interface pointer?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good spot, although actually I think it's probably fine simplify and just check vkey for equality.

Comment thread witness.go Outdated
alreadyAdded = true
break
}
witName = fmt.Sprintf("%s-%d", witName, anonGroupNameCounter.Add(1))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

By renaming the identical key to -1, one single witness signature would be treated as more than one quorum, potentially bypassing the quorum threshold.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is where the key is different (although same name), but actually I think this is also only possible with an invalid policy, so I'll just disallow it.

@AlCutter
AlCutter force-pushed the migrate_tlog_policy_1 branch from 4163052 to 83d6267 Compare September 9, 2026 09:40
Comment thread witness.go Outdated
Comment on lines +260 to +264
if wg.N == 0 || len(wg.Components) == 0 {
return policy.TLogPolicy{
Quorum: "none",
}, nil
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a chance that we need to return optional groups when N = 0?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good spot, updated.

Comment thread witness.go Outdated
}

func (wg WitnessGroup) toPolicy() (policy.TLogPolicy, error) {
if wg.N == 0 || len(wg.Components) == 0 {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we return an error for WitnessGroup{N: 1, Components: nil}?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, probably overkill given this is all being deprecated, but why not :)

@AlCutter
AlCutter force-pushed the migrate_tlog_policy_1 branch from 83d6267 to 1b152e5 Compare September 9, 2026 10:54
Comment thread witness.go

// populatePolicy recursively populates a policy.TLogPolicy from a WitnessGroup.
// It returns the name of the group and an error if any part of the population fails.
func populatePolicy(p *policy.TLogPolicy, wg WitnessGroup) (string, error) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The logic here doesn't check the duplicate subgroup name, so it is possible to have the same name appearing more than once in p.Groups. Is that allowed?

sub := NewWitnessGroup(1, w1, w2);
root := NewWitnessGroup(2, sub, sub)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's not allowed, added a check for that.

This code is all rather temporary though, I'm trying to deprecate and remove all this code which operates in terms of NewWitness and NewWitnessGroup.

@AlCutter
AlCutter force-pushed the migrate_tlog_policy_1 branch from 1b152e5 to e49e664 Compare September 9, 2026 11:05
Comment thread witness.go
}
alreadyAdded := false
for _, existing := range p.Witnesses {
if existing.Name == witName {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The current logic doesn't return an error when multiple witnesses use the different name but the same public key. Although this sounds impossible, it's a violation in the tlog-policy specification.

https://github.com/C2SP/C2SP/blob/main/tlog-policy.md#public-key-representation

@AlCutter
AlCutter force-pushed the migrate_tlog_policy_1 branch from e49e664 to 1a60fb9 Compare September 9, 2026 11:21

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Performance Alert ⚠️

Possible performance regression was detected for benchmark.
Benchmark result of this commit is worse than the previous benchmark result exceeding threshold 1.50.

Benchmark suite Current: df1d8ff Previous: f1f48c4 Ratio
BenchmarkDedup (github.com/transparency-dev/tessera) 4432800 ns/op 900912 B/op 18767 allocs/op 2207022 ns/op 886850 B/op 18650 allocs/op 2.01
BenchmarkDedup (github.com/transparency-dev/tessera) - ns/op 4432800 ns/op 2207022 ns/op 2.01
BenchmarkLeafBundle_UnmarshalText (github.com/transparency-dev/tessera/api) 11550 ns/op 6528 B/op 1 allocs/op 1351 ns/op 6528 B/op 1 allocs/op 8.55
BenchmarkLeafBundle_UnmarshalText (github.com/transparency-dev/tessera/api) - ns/op 11550 ns/op 1351 ns/op 8.55
BenchmarkProofBuilder/InclusionProof/WarmCache (github.com/transparency-dev/tessera/client) 130331 ns/op 15378 B/op 180 allocs/op 56548 ns/op 15353 B/op 180 allocs/op 2.30
BenchmarkProofBuilder/InclusionProof/WarmCache (github.com/transparency-dev/tessera/client) - ns/op 130331 ns/op 56548 ns/op 2.30
BenchmarkProofBuilder/InclusionProof/ColdCache (github.com/transparency-dev/tessera/client) 1274427 ns/op 689100 B/op 3555 allocs/op 554836 ns/op 689106 B/op 3555 allocs/op 2.30
BenchmarkProofBuilder/InclusionProof/ColdCache (github.com/transparency-dev/tessera/client) - ns/op 1274427 ns/op 554836 ns/op 2.30
BenchmarkProofBuilder/ConsistencyProof/WarmCache (github.com/transparency-dev/tessera/client) 125684 ns/op 15453 B/op 180 allocs/op 56420 ns/op 15411 B/op 180 allocs/op 2.23
BenchmarkProofBuilder/ConsistencyProof/WarmCache (github.com/transparency-dev/tessera/client) - ns/op 125684 ns/op 56420 ns/op 2.23

This comment was automatically generated by workflow using github-action-benchmark.

@AlCutter
AlCutter force-pushed the migrate_tlog_policy_1 branch from 1a60fb9 to df1d8ff Compare September 9, 2026 11:31
@AlCutter
AlCutter merged commit cd4606e into main Sep 10, 2026
29 of 30 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants