Skip to content

Commit 4d53d75

Browse files
robinbryceRobin Bryce
andauthored
feat: configurable seal version for test committer/confirmer (#32)
AB#10098 Co-authored-by: Robin Bryce <[email protected]>
1 parent 4b33c6e commit 4d53d75

File tree

5 files changed

+82
-26
lines changed

5 files changed

+82
-26
lines changed

massifs/massifcontextverified.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,10 @@ func (mc *MassifContext) verifyContextV1(
233233
// before replicating the new data.
234234
if options.trustedBaseState != nil {
235235

236+
if options.trustedBaseState.Version == int(MMRStateVersion0) {
237+
return nil, fmt.Errorf("unsupported MMR state version 0 (you should promote to v1 on demand using mmr.PeakHashes)")
238+
}
239+
236240
ok, _, err = mmr.CheckConsistency(
237241
mc, sha256.New(),
238242
options.trustedBaseState.MMRSize,

massifs/massifpeakstack_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -535,7 +535,7 @@ func TestPeakStack_Height4Massif2to3Size63(t *testing.T) {
535535
iBaseLeafNode45 := iPeakNode45 - mmr.IndexHeight(iPeakNode45)
536536
iLeaf45 := mmr.LeafCount(iBaseLeafNode45)
537537

538-
hsz := mmr.HeightSize(uint64(committer.cfg.MassifHeight))
538+
hsz := mmr.HeightSize(uint64(committer.Cfg.MassifHeight))
539539
hlc := (hsz + 1) / 2
540540
mi30 := iLeaf30 / hlc
541541
mcPeakNode30, err := massifReader.GetMassif(ctx, tenantIdentity, mi30)

massifs/testcommitter.go

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,11 @@ type TestCommitterConfig struct {
2323
CommitmentEpoch uint32
2424
MassifHeight uint8
2525
SealOnCommit bool
26+
SealerKey *ecdsa.PrivateKey
27+
UseV0Seals bool
2628
}
2729
type TestMinimalCommitter struct {
28-
cfg TestCommitterConfig
30+
Cfg TestCommitterConfig
2931
log logger.Logger
3032
g mmrtesting.TestGenerator
3133
tc mmrtesting.TestContext
@@ -36,7 +38,6 @@ type TestMinimalCommitter struct {
3638
SealIssuer string
3739
RootSigner RootSigner
3840
CoseSigner *azkeys.TestCoseSigner
39-
SealerKey *ecdsa.PrivateKey
4041
SealerPubKey *ecdsa.PublicKey
4142
}
4243

@@ -51,22 +52,24 @@ func NewTestMinimalCommitter(
5152

5253
log := logger.Sugar.WithServiceName("merklebuilderv1")
5354
c := TestMinimalCommitter{
54-
cfg: cfg,
55+
Cfg: cfg,
5556
log: logger.Sugar.WithServiceName("TestCommitter"),
5657
tc: tc,
5758
g: g,
5859
committer: *NewMassifCommitter(
5960
MassifCommitterConfig{CommitmentEpoch: cfg.CommitmentEpoch}, log, tc.GetStorer()),
6061
leafGenerator: leafGenerator,
6162
}
62-
if !c.cfg.SealOnCommit {
63+
if !c.Cfg.SealOnCommit {
6364
return c, nil
6465
}
6566

6667
c.SealIssuer = "seal.datatrails.ai"
67-
key := TestGenerateECKey(tc.T, elliptic.P256())
68-
c.SealerKey = &key
69-
c.CoseSigner = azkeys.NewTestCoseSigner(tc.T, key)
68+
if c.Cfg.SealerKey == nil {
69+
key := TestGenerateECKey(tc.T, elliptic.P256())
70+
c.Cfg.SealerKey = &key
71+
}
72+
c.CoseSigner = azkeys.NewTestCoseSigner(tc.T, *c.Cfg.SealerKey)
7073
codec, err := NewRootSignerCodec()
7174
require.NoError(tc.T, err)
7275
c.RootSigner = NewRootSigner(c.SealIssuer, codec)
@@ -75,12 +78,12 @@ func NewTestMinimalCommitter(
7578

7679
func (c *TestMinimalCommitter) GetCurrentContext(
7780
ctx context.Context, tenantIdentity string, massifHeight uint8) (MassifContext, error) {
78-
return c.committer.GetCurrentContext(ctx, tenantIdentity, c.cfg.MassifHeight)
81+
return c.committer.GetCurrentContext(ctx, tenantIdentity, c.Cfg.MassifHeight)
7982
}
8083

8184
// ContextCommitted seals the current massif context if the context is configure with SealOnCommit
8285
func (c *TestMinimalCommitter) ContextCommitted(ctx context.Context, tenantIdentity string, mc MassifContext) error {
83-
if !c.cfg.SealOnCommit {
86+
if !c.Cfg.SealOnCommit {
8487
return nil
8588
}
8689

@@ -98,10 +101,18 @@ func (c *TestMinimalCommitter) ContextCommitted(ctx context.Context, tenantIdent
98101
MMRSize: mmrSize,
99102
Peaks: peaks,
100103
Timestamp: time.Now().UnixMilli(),
101-
CommitmentEpoch: c.cfg.CommitmentEpoch,
104+
CommitmentEpoch: c.Cfg.CommitmentEpoch,
102105
IDTimestamp: mc.GetLastIdTimestamp(),
103106
}
104107

108+
if c.Cfg.UseV0Seals {
109+
// downgrade the seal to v0
110+
state.LegacySealRoot = mmr.HashPeaksRHS(sha256.New(), peaks)
111+
state.Peaks = nil
112+
state.Version = int(MMRStateVersion0)
113+
// everything else is the same
114+
}
115+
105116
subject := TenantMassifBlobPath(tenantIdentity, uint64(mc.Start.MassifIndex))
106117
publicKey, err := c.CoseSigner.PublicKey()
107118
if err != nil {
@@ -137,7 +148,7 @@ func (c *TestMinimalCommitter) AddLeaves(
137148
if count == 0 {
138149
return nil
139150
}
140-
mc, err := c.committer.GetCurrentContext(ctx, tenantIdentity, c.cfg.MassifHeight)
151+
mc, err := c.committer.GetCurrentContext(ctx, tenantIdentity, c.Cfg.MassifHeight)
141152
if err != nil {
142153
c.log.Infof("AddLeaves: %v", err)
143154
return err
@@ -162,7 +173,7 @@ func (c *TestMinimalCommitter) AddLeaves(
162173
if err != nil {
163174
return err
164175
}
165-
mc, err = c.committer.GetCurrentContext(ctx, tenantIdentity, c.cfg.MassifHeight)
176+
mc, err = c.committer.GetCurrentContext(ctx, tenantIdentity, c.Cfg.MassifHeight)
166177
if err != nil {
167178
c.log.Infof("AddLeaves: %v", err)
168179
return err

massifs/testlocalreadercontext.go

Lines changed: 53 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ package massifs
44

55
import (
66
"context"
7+
"crypto/ecdsa"
78
"strings"
89
"testing"
910

@@ -18,45 +19,62 @@ type TestLocalReaderContext struct {
1819
AzuriteContext mmrtesting.TestContext
1920
TestConfig mmrtesting.TestConfig
2021
CommitterConfig TestCommitterConfig
22+
LogOptions TestLogOptions
2123

2224
G mmrtesting.TestGenerator
2325
// We use a regular massif reader attached to azurite to test the local massif reader.
2426
AzuriteReader MassifReader
2527
}
2628

27-
// TestLogCreatorContext holds the context data resulting from a call to CreateLog
29+
// TestLogOptions holds the context data resulting from a call to CreateLog
2830
// Unless one or more of the TEstCreateLogOptions are used, the context will not have anything interesting in it.
29-
type TestLogCreatorContext struct {
30-
Preimages map[uint64][]byte
31+
type TestLogOptions struct {
32+
Preimages map[uint64][]byte
33+
ContinueExisting bool // if true, don'
34+
SealKey *ecdsa.PrivateKey
35+
UsingV0Seals bool
3136
}
3237

33-
type TestCreateLogOption func(*TestLogCreatorContext)
38+
type TestLogOption func(*TestLogOptions)
3439

35-
func TestWithCreateLogPreImages() TestCreateLogOption {
36-
return func(c *TestLogCreatorContext) {
40+
func TestWithCreateLogPreImages() TestLogOption {
41+
return func(c *TestLogOptions) {
3742
c.Preimages = make(map[uint64][]byte)
3843
}
3944
}
4045

46+
func TestWithSealKey(key *ecdsa.PrivateKey) TestLogOption {
47+
return func(c *TestLogOptions) {
48+
c.SealKey = key
49+
}
50+
}
51+
52+
func TestWithV0Seals() TestLogOption {
53+
return func(c *TestLogOptions) {
54+
c.UsingV0Seals = true
55+
}
56+
}
57+
4158
// CreateLog creates a log with the given tenant identity, massif height, and mmr size,
4259
// any previous seal or massif blobs for the same tenant are first deleted
60+
// To create a single incomplete massif, call AddLeavesToLog with a leafCount instead of CreateLog
4361
func (c *TestLocalReaderContext) CreateLog(
4462
tenantIdentity string, massifHeight uint8, massifCount uint32,
45-
opts ...TestCreateLogOption) {
63+
opts ...TestLogOption) {
4664

47-
logContext := &TestLogCreatorContext{}
65+
options := &TestLogOptions{}
4866
for _, opt := range opts {
49-
opt(logContext)
67+
opt(options)
5068
}
5169

5270
generator := MMRTestingGenerateNumberedLeaf
5371

5472
// If the caller needs to work with the pre-images we wrap the generator to retain them
55-
if logContext.Preimages != nil {
73+
if options.Preimages != nil {
5674
generator = func(tenantIdentity string, base, i uint64) mmrtesting.AddLeafArgs {
5775

5876
args := generator(tenantIdentity, base, i)
59-
logContext.Preimages[base+i] = args.Value
77+
options.Preimages[base+i] = args.Value
6078
return args
6179
}
6280
}
@@ -68,24 +86,47 @@ func (c *TestLocalReaderContext) CreateLog(
6886
CommitmentEpoch: 1,
6987
MassifHeight: massifHeight,
7088
SealOnCommit: true, // create seals for each massif as we go
89+
SealerKey: options.SealKey,
90+
UseV0Seals: options.UsingV0Seals,
7191
}, c.AzuriteContext, c.G, generator)
7292
require.NoError(c.AzuriteContext.T, err)
7393

7494
leavesPerMassif := mmr.HeightIndexLeafCount(uint64(massifHeight) - 1)
7595

96+
// using base = 0 means the caller can't predict the leaf hash based on the mmr index, but otherwise it's fine
97+
// if the caller is overriding the generator, they can do what they like
7698
err = committer.AddLeaves(context.TODO(), tenantIdentity, 0, leavesPerMassif*uint64(massifCount))
7799
require.NoError(c.AzuriteContext.T, err)
78100
}
79101

80102
// AddLeavesToLog adds the requested number of leaves to the log for the given
81103
// tenant identity. Note the massifHeight must be the same as was provided to
82104
// the corresponding CreateLog call
83-
func (c *TestLocalReaderContext) AddLeavesToLog(tenantIdentity string, massifHeight uint8, leafCount int) {
105+
// To create a single incomplete massif, call AddLeavesToLog with a leafCount instead of CreateLog
106+
func (c *TestLocalReaderContext) AddLeavesToLog(tenantIdentity string, massifHeight uint8, leafCount int, opts ...TestLogOption) {
107+
108+
options := &TestLogOptions{}
109+
for _, opt := range opts {
110+
opt(options)
111+
}
112+
generator := MMRTestingGenerateNumberedLeaf
113+
114+
// If the caller needs to work with the pre-images we wrap the generator to retain them
115+
if options.Preimages != nil {
116+
generator = func(tenantIdentity string, base, i uint64) mmrtesting.AddLeafArgs {
117+
118+
args := generator(tenantIdentity, base, i)
119+
options.Preimages[base+i] = args.Value
120+
return args
121+
}
122+
}
84123

85124
committer, err := NewTestMinimalCommitter(TestCommitterConfig{
86125
CommitmentEpoch: 1,
87126
MassifHeight: massifHeight,
88127
SealOnCommit: true, // create seals for each massif as we go
128+
SealerKey: options.SealKey,
129+
UseV0Seals: options.UsingV0Seals,
89130
}, c.AzuriteContext, c.G, MMRTestingGenerateNumberedLeaf)
90131
require.NoError(c.AzuriteContext.T, err)
91132

tests/go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ replace (
1212

1313
require (
1414
github.com/datatrails/go-datatrails-common v0.18.0
15-
github.com/datatrails/go-datatrails-merklelog/massifs v0.0.0-00010101000000-000000000000
15+
github.com/datatrails/go-datatrails-merklelog/massifs v0.2.1
1616
github.com/datatrails/go-datatrails-merklelog/mmr v0.1.1
1717
github.com/stretchr/testify v1.9.0
1818
)

0 commit comments

Comments
 (0)