-
Notifications
You must be signed in to change notification settings - Fork 199
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Draft: MRENCLAVE support antehandler #1676
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,20 +2,53 @@ package keeper | |
|
||
import ( | ||
"encoding/binary" | ||
"errors" | ||
"fmt" | ||
"regexp" | ||
|
||
"cosmossdk.io/core/store" | ||
upgradetypes "cosmossdk.io/x/upgrade/types" | ||
"github.com/cosmos/cosmos-sdk/codec" | ||
types1 "github.com/cosmos/cosmos-sdk/codec/types" | ||
sdk "github.com/cosmos/cosmos-sdk/types" | ||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" | ||
govkeeper "github.com/cosmos/cosmos-sdk/x/gov/keeper" | ||
v1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1" | ||
"github.com/scrtlabs/SecretNetwork/x/compute/internal/types" | ||
) | ||
|
||
// CountTXDecorator ante handler to count the tx position in a block. | ||
type CountTXDecorator struct { | ||
appcodec codec.Codec | ||
govkeeper govkeeper.Keeper // we need the govkeeper to access stored proposals | ||
storeService store.KVStoreService | ||
} | ||
|
||
// NewCountTXDecorator constructor | ||
func NewCountTXDecorator(storeService store.KVStoreService) *CountTXDecorator { | ||
return &CountTXDecorator{storeService: storeService} | ||
func NewCountTXDecorator(appcodec codec.Codec, govkeeper govkeeper.Keeper, storeService store.KVStoreService) *CountTXDecorator { | ||
return &CountTXDecorator{ | ||
appcodec: appcodec, | ||
govkeeper: govkeeper, | ||
storeService: storeService, | ||
} | ||
} | ||
|
||
// Function to find and return the MREnclaveHash string from input | ||
func findMREnclaveHash(input string) (string, error) { | ||
// Define the regular expression pattern with a capture group for the SHA256 hash | ||
pattern := `^MREnclaveHash:([a-fA-F0-9]{64})$` | ||
|
||
re := regexp.MustCompile(pattern) | ||
|
||
matches := re.FindStringSubmatch(input) | ||
|
||
// If no match is found, return an error | ||
if len(matches) < 2 { | ||
return "", errors.New("MREnclaveHash not found or invalid in the input string") | ||
} | ||
|
||
// The SHA256 hash is captured in the first capturing group, which is matches[1] | ||
return matches[1], nil | ||
} | ||
|
||
// AnteHandle handler stores a tx counter with current height encoded in the store to let the app handle | ||
|
@@ -44,9 +77,78 @@ func (a CountTXDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, | |
ctx.Logger().Error("compute ante store set", "store", err.Error()) | ||
} | ||
|
||
for _, msg := range tx.GetMsgs() { | ||
// Check if this is a MsgUpgradeProposalPassed | ||
msgUpgrade, ok := msg.(*types.MsgUpgradeProposalPassed) | ||
if ok { | ||
err = a.verifyUpgradeProposal(ctx, msgUpgrade) | ||
if err != nil { | ||
return ctx, err | ||
} | ||
} | ||
} | ||
|
||
return next(types.WithTXCounter(ctx, txCounter), tx, simulate) | ||
} | ||
|
||
// extractInfoFromProposalMessages extracts the "info" field from the proposal message. | ||
// This "info" contains the MREnclaveHash. | ||
func extractInfoFromProposalMessages(message *types1.Any, cdc codec.Codec) (string, error) { | ||
var softwareUpgradeMsg *upgradetypes.MsgSoftwareUpgrade | ||
err := cdc.UnpackAny(message, &softwareUpgradeMsg) | ||
if err != nil { | ||
return "", fmt.Errorf("failed to unpack message: %w", err) | ||
} | ||
|
||
return softwareUpgradeMsg.Plan.Info, nil | ||
} | ||
|
||
// verifyUpgradeProposal verifies the latest passed upgrade proposal to ensure the MREnclave hash matches. | ||
func (a *CountTXDecorator) verifyUpgradeProposal(ctx sdk.Context, msgUpgrade *types.MsgUpgradeProposalPassed) error { | ||
iterator, err := a.govkeeper.Proposals.Iterate(ctx, nil) | ||
if err != nil { | ||
ctx.Logger().Error("Failed to get the iterator of proposals!", err.Error()) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You may want to return the actual error |
||
} | ||
defer iterator.Close() // Ensure the iterator is closed after use | ||
|
||
var latestProposal *v1.Proposal = nil | ||
var latestMREnclaveHash string | ||
|
||
// Iterate through the proposals | ||
for ; iterator.Valid(); iterator.Next() { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. you should use for range iterator construct |
||
// Get the proposal value | ||
proposal, err := iterator.Value() | ||
if err != nil { | ||
ctx.Logger().Error("Failed to get the proposal from iterator!", err.Error()) | ||
return errors.New("Failed to get the proposal from iterator!") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. user fmt.Errorf. No need to use ! sign |
||
} | ||
// Check if the proposal has passed and is of type MsgSoftwareUpgrade | ||
if proposal.Status == v1.ProposalStatus_PROPOSAL_STATUS_PASSED { | ||
if len(proposal.GetMessages()) > 0 && proposal.Messages[0].GetTypeUrl() == "/cosmos.upgrade.v1beta1.MsgSoftwareUpgrade" { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please use a const for "/cosmos.upgrade.v1beta1.MsgSoftwareUpgrade" |
||
// Update latestProposal if this proposal is newer (has a higher ID) | ||
if latestProposal == nil || proposal.Id > latestProposal.Id { | ||
latestProposal = &proposal | ||
} | ||
} | ||
} | ||
} | ||
|
||
// If we found the MsgSoftwareUpgrade latest passed proposal, extract the MREnclaveHash from it | ||
if latestProposal != nil { | ||
info, err := extractInfoFromProposalMessages(latestProposal.Messages[0], a.appcodec) | ||
if err != nil { | ||
return fmt.Errorf("Failed to extract info with MREnclave hash from Proposal, error: %w", err) | ||
} | ||
latestMREnclaveHash, _ = findMREnclaveHash(info) | ||
} | ||
|
||
// Check if the MREnclave hash matches the one in the MsgUpgradeProposalPassed message | ||
if latestMREnclaveHash != string(msgUpgrade.MrEnclaveHash) { | ||
return sdkerrors.ErrUnauthorized.Wrap("software upgrade proposal: mrenclave hash mismatch") | ||
} | ||
return nil | ||
} | ||
|
||
func encodeHeightCounter(height int64, counter uint32) []byte { | ||
b := make([]byte, 4) | ||
binary.BigEndian.PutUint32(b, counter) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ctx.Logger().Error(fmt.Sprintf("Governance Keeper Proposal: %s", err))
No need to use ! sign.