Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .changelog/6331.breaking.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
go/common/sgx/pcs/policy: Add FMSPC whitelist to quote policy
4 changes: 2 additions & 2 deletions go/common/node/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -574,7 +574,7 @@ func HashRAK(rak signature.PublicKey) hash.Hash {
}

// Verify verifies the node's TEE capabilities, at the provided timestamp and height.
func (c *CapabilityTEE) Verify(teeCfg *TEEFeatures, ts time.Time, height uint64, constraints []byte, nodeID signature.PublicKey) error {
func (c *CapabilityTEE) Verify(teeCfg *TEEFeatures, ts time.Time, height uint64, constraints []byte, nodeID signature.PublicKey, isFeatureVersion242 bool) error {
switch c.Hardware {
case TEEHardwareIntelSGX:
// Parse SGX remote attestation.
Expand All @@ -591,7 +591,7 @@ func (c *CapabilityTEE) Verify(teeCfg *TEEFeatures, ts time.Time, height uint64,
if err := cbor.Unmarshal(constraints, &sc); err != nil {
return fmt.Errorf("node: malformed SGX constraints: %w", err)
}
if err := sc.ValidateBasic(teeCfg); err != nil {
if err := sc.ValidateBasic(teeCfg, isFeatureVersion242); err != nil {
Copy link
Member

Choose a reason for hiding this comment

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

How will this look when other features are added? Will there be additional version flags like these? Should we instead pass context or somehow make this part of teeCfg?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

How will this look when other features are added? Will there be additional version flags like these? Should we instead pass context or somehow make this part of teeCfg?

  • If other features are added in the same version, than this remains the same.
  • If another feature is added in e.g. 24.3, than we would need to add a new flag isFeatureVersion243, pass context or something else. But the trick is that we don't need to do this as this code should be removed in version 24.3, after we do the upgrade, because state sync will work without these changes, as they are here just to prevent filling the whitelist.

Copy link
Member

@kostko kostko Sep 29, 2025

Choose a reason for hiding this comment

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

But I guess this can only be removed if there are no transactions posted that would violate this constraint? As otherwise iterative block sync would fail.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

But I guess this can only be removed if there are no transactions posted that would violate this constraint? As otherwise iterative block sync would fail.

No, wrong thinking. This is here to forbid posting transactions that would violate this constraint (non-empty whitelist) until we do the feature version bump.

This validation ensures we don't have consensus problems, as once we merge this PR in oasis core version 25.6, a new node running version 25.6 could post a policy with non-empty whitelist while an old node with version 25.5 would reject it. Having this check ensures that new nodes must submit empty whitelists until we do the feature version bump. And once we do the bump, this validation can be removed as it is not needed anymore as all nodes should be running at least 25.6. version.

Copy link
Member

Choose a reason for hiding this comment

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

But what happens if someone posted a transaction with a non-empty whitelist right now and the transaction is included in a block, but fails (because currently it is an unknown field)? Then once this check is removed in a future version, syncing from genesis will cause divergence when processing this transaction (which will now succeed during iterative block sync)? So this works as long as no such transaction is included in a block before the governance vote.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Oh, now I see. Yes, that would be a problem.

I suggest we merge these changes, and after we upgrade, we do state sync to check that there are no such transactions (this means that there could still be a tx with a whitelist but also with another unknown field, and that field would still fail the tx). If there are, we prettify the code, if not, we can remove these changes.

Copy link
Member

Choose a reason for hiding this comment

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

Sounds good to me.

Copy link
Contributor

Choose a reason for hiding this comment

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

I suggest we merge these changes, and after we upgrade, we do state sync to check that there are no such transactions.

Looks safe to me and indeed simpler.

If we find such transactions then probably SGXConstraintsV2 behind feature flag might be cleaner on the long run (unlikely to happen so lets ignore this).

return fmt.Errorf("node: malformed SGX constraints: %w", err)
}

Expand Down
9 changes: 8 additions & 1 deletion go/common/node/sgx.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ func (sc *SGXConstraints) MarshalCBOR() ([]byte, error) {
}

// ValidateBasic performs basic structure validity checks.
func (sc *SGXConstraints) ValidateBasic(cfg *TEEFeatures) error {
func (sc *SGXConstraints) ValidateBasic(cfg *TEEFeatures, isFeatureVersion242 bool) error {
if cfg == nil {
cfg = &emptyFeatures
}
Expand All @@ -116,6 +116,13 @@ func (sc *SGXConstraints) ValidateBasic(cfg *TEEFeatures) error {
return fmt.Errorf("TDX policy not supported")
}

// Check that policy is compliant with the current feature version.
if sc.Policy != nil {
if err := sc.Policy.Validate(isFeatureVersion242); err != nil {
return fmt.Errorf("invalid policy: %w", err)
}
}

return nil
}

Expand Down
8 changes: 4 additions & 4 deletions go/common/node/sgx_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ func TestSGXConstraintsV0(t *testing.T) {
err = cbor.Unmarshal(raw, &sc)
require.NoError(err, "Decode V0 SGX constraints")

err = sc.ValidateBasic(nil)
err = sc.ValidateBasic(nil, true)
require.NoError(err, "ValidateBasic V0 SGX constraints")

enc := cbor.Marshal(sc)
Expand Down Expand Up @@ -60,11 +60,11 @@ func TestSGXConstraintsV1(t *testing.T) {
},
},
}
err = sc.ValidateBasic(nil)
err = sc.ValidateBasic(nil, true)
require.Error(err, "ValidateBasic V1 SGX constraints without PCS support")
err = sc.ValidateBasic(&TEEFeatures{})
err = sc.ValidateBasic(&TEEFeatures{}, true)
require.Error(err, "ValidateBasic V1 SGX constraints without PCS support")
err = sc.ValidateBasic(&TEEFeatures{SGX: TEEFeaturesSGX{PCS: true}})
err = sc.ValidateBasic(&TEEFeatures{SGX: TEEFeaturesSGX{PCS: true}}, true)
require.NoError(err, "ValidateBasic V1 SGX constraints")
}

Expand Down
4 changes: 4 additions & 0 deletions go/common/sgx/pcs/policy.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ type QuotePolicy struct {
// valid. TCB bundles containing smaller values will be invalid.
MinTCBEvaluationDataNumber uint32 `json:"min_tcb_evaluation_data_number" yaml:"min_tcb_evaluation_data_number"`

// FMSPCWhitelist is a list of hexadecimal encoded FMSPCs specifying which processor
// packages and platform instances are allowed.
FMSPCWhitelist []string `json:"fmspc_whitelist,omitempty" yaml:"fmspc_whitelist,omitempty"`

// FMSPCBlacklist is a list of hexadecimal encoded FMSPCs specifying which processor
// packages and platform instances are blocked.
FMSPCBlacklist []string `json:"fmspc_blacklist,omitempty" yaml:"fmspc_blacklist,omitempty"`
Expand Down
3 changes: 2 additions & 1 deletion go/common/sgx/pcs/quote.go
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,8 @@ func (q *Quote) Verify(policy *QuotePolicy, ts time.Time, tcb *TCBBundle) (*sgx.
policy = &QuotePolicy{
TCBValidityPeriod: 30,
MinTCBEvaluationDataNumber: DefaultMinTCBEvaluationDataNumber,
FMSPCBlacklist: []string{},
FMSPCWhitelist: make([]string, 0),
FMSPCBlacklist: make([]string, 0),
}
}

Expand Down
25 changes: 24 additions & 1 deletion go/common/sgx/pcs/quote_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,14 +121,37 @@ func TestQuoteV3_ECDSA_P256_PCK_CertificateChain(t *testing.T) {
require.Error(err, "Quote verification should fail for invalid TCB evaluation data number")
require.ErrorContains(err, "pcs/quote: failed to verify TCB bundle: pcs/tcb: failed to verify QE identity: pcs/tcb: invalid QE identity: pcs/tcb: invalid QE evaluation data number")

// Test whitelisted FMSPC.
quotePolicy = &QuotePolicy{
TCBValidityPeriod: 90,
FMSPCWhitelist: []string{},
}
_, err = quote.Verify(quotePolicy, now, &tcbBundle)
require.NoError(err, "Quote verification should succeed for whitelisted FMSPCs")

quotePolicy = &QuotePolicy{
TCBValidityPeriod: 90,
FMSPCWhitelist: []string{"00606A000000"},
}
_, err = quote.Verify(quotePolicy, now, &tcbBundle)
require.NoError(err, "Quote verification should succeed for whitelisted FMSPCs")

quotePolicy = &QuotePolicy{
TCBValidityPeriod: 90,
FMSPCWhitelist: []string{"00606A000001"},
}
_, err = quote.Verify(quotePolicy, now, &tcbBundle)
require.Error(err, "Quote verification should fail for non-whitelisted FMSPCs")
require.ErrorContains(err, "pcs/quote: failed to verify TCB bundle: pcs/tcb: failed to verify TCB info: pcs/tcb: invalid TCB info: pcs/tcb: FMSPC is not whitelisted")

// Test blacklisted FMSPC.
quotePolicy = &QuotePolicy{
TCBValidityPeriod: 90,
FMSPCBlacklist: []string{"00606A000000"},
}
_, err = quote.Verify(quotePolicy, now, &tcbBundle)
require.Error(err, "Quote verification should fail for blacklisted FMSPCs")
require.ErrorContains(err, "pcs/quote: failed to verify TCB bundle: pcs/tcb: failed to verify TCB info: pcs/tcb: invalid TCB info: pcs/tcb: blacklisted FMSPC")
require.ErrorContains(err, "pcs/quote: failed to verify TCB bundle: pcs/tcb: failed to verify TCB info: pcs/tcb: invalid TCB info: pcs/tcb: FMSPC is blacklisted")

// Test TCB info certificates missing.
tcbBundle2 := TCBBundle{
Expand Down
9 changes: 7 additions & 2 deletions go/common/sgx/pcs/tcb.go
Original file line number Diff line number Diff line change
Expand Up @@ -270,9 +270,14 @@ func (ti *TCBInfo) validate(teeType TeeType, ts time.Time, policy *QuotePolicy)
return fmt.Errorf("pcs/tcb: invalid TCB evaluation data number")
}

// Validate FMSPC not blacklisted.
// Validate FMSPC is whitelisted.
if len(policy.FMSPCWhitelist) > 0 && !slices.Contains(policy.FMSPCWhitelist, ti.FMSPC) {
return fmt.Errorf("pcs/tcb: FMSPC is not whitelisted")
}

// Validate FMSPC is not blacklisted.
if slices.Contains(policy.FMSPCBlacklist, ti.FMSPC) {
return fmt.Errorf("pcs/tcb: blacklisted FMSPC")
return fmt.Errorf("pcs/tcb: FMSPC is blacklisted")
}

return nil
Expand Down
17 changes: 17 additions & 0 deletions go/common/sgx/quote/quote.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,3 +64,20 @@ type Policy struct {
IAS *ias.QuotePolicy `json:"ias,omitempty" yaml:"ias,omitempty"`
PCS *pcs.QuotePolicy `json:"pcs,omitempty" yaml:"pcs,omitempty"`
}

// Validate validates the policy.
func (p *Policy) Validate(isFeatureVersion242 bool) error {
if isFeatureVersion242 {
return nil
}

if p.PCS == nil {
return nil
}

if len(p.PCS.FMSPCWhitelist) == 0 {
return nil
}

return fmt.Errorf("fmspc whitelist should be empty")
}
12 changes: 9 additions & 3 deletions go/common/sgx/quote/quote_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,12 @@ pcs:
disabled: false
tcb_validity_period: 30
min_tcb_evaluation_data_number: 17
fmspc_blacklist:
fmspc_whitelist:
- "000000000000"
- "00606A000000"
fmspc_blacklist:
- "000000000001"
- "00606A000001"
`
var dec Policy
err := yaml.Unmarshal([]byte(testCase1), &dec)
Expand All @@ -27,7 +30,10 @@ pcs:
require.EqualValues(false, dec.PCS.Disabled)
require.EqualValues(30, dec.PCS.TCBValidityPeriod)
require.EqualValues(17, dec.PCS.MinTCBEvaluationDataNumber)
require.Len(dec.PCS.FMSPCWhitelist, 2)
require.EqualValues("000000000000", dec.PCS.FMSPCWhitelist[0])
require.EqualValues("00606A000000", dec.PCS.FMSPCWhitelist[1])
require.Len(dec.PCS.FMSPCBlacklist, 2)
require.EqualValues("000000000000", dec.PCS.FMSPCBlacklist[0])
require.EqualValues("00606A000000", dec.PCS.FMSPCBlacklist[1])
require.EqualValues("000000000001", dec.PCS.FMSPCBlacklist[0])
require.EqualValues("00606A000001", dec.PCS.FMSPCBlacklist[1])
}
2 changes: 1 addition & 1 deletion go/consensus/cometbft/apps/keymanager/common/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ func RegistryRuntimes(ctx *tmapi.Context, doc *genesis.Document, epoch beacon.Ep
regSt := doc.Registry
rtMap := make(map[common.Namespace]*registry.Runtime)
for _, rt := range regSt.Runtimes {
err := registry.VerifyRuntime(&regSt.Parameters, ctx.Logger(), rt, true, false, epoch)
err := registry.VerifyRuntime(&regSt.Parameters, ctx.Logger(), rt, true, false, epoch, true)
if err != nil {
ctx.Logger().Error("InitChain: Invalid runtime",
"err", err,
Expand Down
9 changes: 8 additions & 1 deletion go/consensus/cometbft/apps/keymanager/secrets/epoch.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,10 @@ import (
tmapi "github.com/oasisprotocol/oasis-core/go/consensus/cometbft/api"
secretsState "github.com/oasisprotocol/oasis-core/go/consensus/cometbft/apps/keymanager/secrets/state"
registryState "github.com/oasisprotocol/oasis-core/go/consensus/cometbft/apps/registry/state"
"github.com/oasisprotocol/oasis-core/go/consensus/cometbft/features"
"github.com/oasisprotocol/oasis-core/go/keymanager/secrets"
registry "github.com/oasisprotocol/oasis-core/go/registry/api"
"github.com/oasisprotocol/oasis-core/go/upgrade/migrations"
)

func (ext *secretsExt) onEpochChange(ctx *tmapi.Context, epoch beacon.EpochTime) error {
Expand All @@ -26,6 +28,11 @@ func (ext *secretsExt) onEpochChange(ctx *tmapi.Context, epoch beacon.EpochTime)
return fmt.Errorf("failed to get consensus parameters: %w", err)
}

isFeatureVersion242, err := features.IsFeatureVersion(ctx, migrations.Version242)
if err != nil {
return err
}

// Recalculate all the key manager statuses.
//
// Note: This assumes that once a runtime is registered, it never expires.
Expand Down Expand Up @@ -64,7 +71,7 @@ func (ext *secretsExt) onEpochChange(ctx *tmapi.Context, epoch beacon.EpochTime)
return fmt.Errorf("failed to query key manager master secret: %w", err)
}

newStatus := generateStatus(ctx, rt, oldStatus, secret, nodes, params, epoch)
newStatus := generateStatus(ctx, rt, oldStatus, secret, nodes, params, epoch, isFeatureVersion242)
if forceEmit || !bytes.Equal(cbor.Marshal(oldStatus), cbor.Marshal(newStatus)) {
ctx.Logger().Debug("status updated",
"id", newStatus.ID,
Expand Down
6 changes: 4 additions & 2 deletions go/consensus/cometbft/apps/keymanager/secrets/status.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ func generateStatus( // nolint: gocyclo
nodes []*node.Node,
params *registry.ConsensusParameters,
epoch beacon.EpochTime,
isFeatureVersion242 bool,
) *secrets.Status {
status := &secrets.Status{
ID: kmrt.ID,
Expand Down Expand Up @@ -111,7 +112,7 @@ nextNode:
continue nextNode
}

initResponse, err := VerifyExtraInfo(ctx.Logger(), n.ID, kmrt, nodeRt, ts, height, params)
initResponse, err := VerifyExtraInfo(ctx.Logger(), n.ID, kmrt, nodeRt, ts, height, params, isFeatureVersion242)
if err != nil {
ctx.Logger().Error("failed to validate ExtraInfo", append(vars, "err", err)...)
continue nextNode
Expand Down Expand Up @@ -231,8 +232,9 @@ func VerifyExtraInfo(
ts time.Time,
height uint64,
params *registry.ConsensusParameters,
isFeatureVersion242 bool,
) (*secrets.InitResponse, error) {
if err := registry.VerifyNodeRuntimeEnclaveIDs(logger, nodeID, nodeRt, rt, params.TEEFeatures, ts, height); err != nil {
if err := registry.VerifyNodeRuntimeEnclaveIDs(logger, nodeID, nodeRt, rt, params.TEEFeatures, ts, height, isFeatureVersion242); err != nil {
return nil, err
}
if nodeRt.ExtraInfo == nil {
Expand Down
18 changes: 9 additions & 9 deletions go/consensus/cometbft/apps/keymanager/secrets/status_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -207,10 +207,10 @@ func TestGenerateStatus(t *testing.T) {
t.Run("No nodes", func(t *testing.T) {
require := require.New(t)

newStatus := generateStatus(ctx, runtimes[0], uninitializedStatus, nil, nodes[0:6], params, epoch)
newStatus := generateStatus(ctx, runtimes[0], uninitializedStatus, nil, nodes[0:6], params, epoch, true)
require.Equal(uninitializedStatus, newStatus, "key manager committee should be empty")

newStatus = generateStatus(ctx, runtimes[0], initializedStatus, nil, nodes[0:6], params, epoch)
newStatus = generateStatus(ctx, runtimes[0], initializedStatus, nil, nodes[0:6], params, epoch, true)
require.Equal(initializedStatus, newStatus, "key manager committee should be empty")
})

Expand All @@ -225,16 +225,16 @@ func TestGenerateStatus(t *testing.T) {
Policy: &policy,
Nodes: []signature.PublicKey{nodes[6].ID},
}
newStatus := generateStatus(ctx, runtimes[0], uninitializedStatus, nil, nodes[6:7], params, epoch)
newStatus := generateStatus(ctx, runtimes[0], uninitializedStatus, nil, nodes[6:7], params, epoch, true)
require.Equal(expStatus, newStatus, "node 6 should form the committee if key manager not initialized")

newStatus = generateStatus(ctx, runtimes[0], expStatus, nil, nodes[6:7], params, epoch)
newStatus = generateStatus(ctx, runtimes[0], expStatus, nil, nodes[6:7], params, epoch, true)
require.Equal(expStatus, newStatus, "node 6 should form the committee if key manager is not secure")

expStatus.IsSecure = true
expStatus.Checksum = checksum
expStatus.Nodes = nil
newStatus = generateStatus(ctx, runtimes[0], initializedStatus, nil, nodes[6:7], params, epoch)
newStatus = generateStatus(ctx, runtimes[0], initializedStatus, nil, nodes[6:7], params, epoch, true)
require.Equal(expStatus, newStatus, "node 6 should not be added to the committee if key manager is secure or checksum differs")
})

Expand All @@ -251,20 +251,20 @@ func TestGenerateStatus(t *testing.T) {
Policy: &policy,
Nodes: []signature.PublicKey{nodes[6].ID},
}
newStatus := generateStatus(ctx, runtimes[0], uninitializedStatus, nil, nodes, params, epoch)
newStatus := generateStatus(ctx, runtimes[0], uninitializedStatus, nil, nodes, params, epoch, true)
require.Equal(expStatus, newStatus, "node 6 should be the source of truth and form the committee")

// If the order is reversed, it should be the other way around.
expStatus.IsSecure = true
expStatus.Nodes = []signature.PublicKey{nodes[7].ID}
newStatus = generateStatus(ctx, runtimes[0], uninitializedStatus, nil, reverse(nodes), params, epoch)
newStatus = generateStatus(ctx, runtimes[0], uninitializedStatus, nil, reverse(nodes), params, epoch, true)
require.Equal(expStatus, newStatus, "node 7 should be the source of truth and form the committee")

// If the key manager is already initialized as secure with a checksum, then all nodes
// except 8 and 9 are ignored.
expStatus.Checksum = checksum
expStatus.Nodes = []signature.PublicKey{nodes[8].ID, nodes[9].ID}
newStatus = generateStatus(ctx, runtimes[0], initializedStatus, nil, nodes, params, epoch)
newStatus = generateStatus(ctx, runtimes[0], initializedStatus, nil, nodes, params, epoch, true)
require.Equal(expStatus, newStatus, "node 7 and 8 should form the committee if key manager is initialized as secure")

// The second key manager.
Expand All @@ -277,7 +277,7 @@ func TestGenerateStatus(t *testing.T) {
Nodes: []signature.PublicKey{nodes[4].ID, nodes[9].ID},
}
initializedStatus.ID = runtimeIDs[1]
newStatus = generateStatus(ctx, runtimes[1], initializedStatus, nil, nodes, params, epoch)
newStatus = generateStatus(ctx, runtimes[1], initializedStatus, nil, nodes, params, epoch, true)
require.Equal(expStatus, newStatus, "node 4 and 9 should form the committee")
})
}
Expand Down
6 changes: 3 additions & 3 deletions go/consensus/cometbft/apps/keymanager/secrets/txs.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,11 +76,11 @@ func (ext *secretsExt) updatePolicy(
status.NextPolicy = sigPol

// Support legacy behavior where the policy was applied immediately.
ok, err := features.IsFeatureVersion(ctx, migrations.Version242)
isFeatureVersion242, err := features.IsFeatureVersion(ctx, migrations.Version242)
if err != nil {
return err
}
if !ok {
if !isFeatureVersion242 {
// Ok, as far as we can tell the new policy is valid, apply it.
//
// Note: The key manager cohort responsible for servicing this ID
Expand All @@ -104,7 +104,7 @@ func (ext *secretsExt) updatePolicy(

nodes, _ := regState.Nodes(ctx)
registry.SortNodeList(nodes)
status = generateStatus(ctx, kmRt, status, nil, nodes, regParams, epoch)
status = generateStatus(ctx, kmRt, status, nil, nodes, regParams, epoch, isFeatureVersion242)
}

if err := state.SetStatus(ctx, status); err != nil {
Expand Down
2 changes: 1 addition & 1 deletion go/consensus/cometbft/apps/registry/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ func (app *Application) InitChain(ctx *abciAPI.Context, _ types.RequestInitChain
if rt == nil {
return fmt.Errorf("registry: genesis runtime index %d is nil", i)
}
err := registry.VerifyRuntime(&st.Parameters, ctx.Logger(), rt, ctx.IsInitChain(), false, epoch)
err := registry.VerifyRuntime(&st.Parameters, ctx.Logger(), rt, ctx.IsInitChain(), false, epoch, true)
if err != nil {
return err
}
Expand Down
9 changes: 8 additions & 1 deletion go/consensus/cometbft/apps/registry/messages.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@ import (
"github.com/oasisprotocol/oasis-core/go/common/cbor"
"github.com/oasisprotocol/oasis-core/go/consensus/cometbft/api"
registryState "github.com/oasisprotocol/oasis-core/go/consensus/cometbft/apps/registry/state"
"github.com/oasisprotocol/oasis-core/go/consensus/cometbft/features"
governance "github.com/oasisprotocol/oasis-core/go/governance/api"
registry "github.com/oasisprotocol/oasis-core/go/registry/api"
"github.com/oasisprotocol/oasis-core/go/upgrade/migrations"
)

func (app *Application) changeParameters(ctx *api.Context, msg any, apply bool) (any, error) {
Expand All @@ -26,6 +28,11 @@ func (app *Application) changeParameters(ctx *api.Context, msg any, apply bool)
return nil, fmt.Errorf("registry: failed to unmarshal consensus parameter changes: %w", err)
}

isFeatureVersion242, err := features.IsFeatureVersion(ctx, migrations.Version242)
if err != nil {
return nil, err
}

// Validate changes against current parameters.
state := registryState.NewMutableState(ctx.State())
params, err := state.ConsensusParameters(ctx)
Expand All @@ -38,7 +45,7 @@ func (app *Application) changeParameters(ctx *api.Context, msg any, apply bool)
if err = changes.Apply(params); err != nil {
return nil, fmt.Errorf("registry: failed to apply consensus parameter changes: %w", err)
}
if err = params.SanityCheck(); err != nil {
if err = params.SanityCheck(isFeatureVersion242); err != nil {
return nil, fmt.Errorf("registry: failed to validate consensus parameters: %w", err)
}

Expand Down
Loading
Loading