From ab59faf0aedfda577d79a8c4c92f5bb075c2511a Mon Sep 17 00:00:00 2001 From: Artur Troian Date: Fri, 26 Jul 2024 13:13:44 -0500 Subject: [PATCH] fix: implement genesis export for audit and cert stores Signed-off-by: Artur Troian --- x/audit/genesis.go | 53 ++++++++++++++++++++++++++++++++++++++--- x/cert/genesis.go | 27 +++++++++++++++++++++ x/cert/keeper/keeper.go | 23 ++++++++++++++++++ x/cert/keeper/key.go | 25 +++++++++++++++++++ 4 files changed, 125 insertions(+), 3 deletions(-) diff --git a/x/audit/genesis.go b/x/audit/genesis.go index c477ba586f..6543b59683 100644 --- a/x/audit/genesis.go +++ b/x/audit/genesis.go @@ -5,25 +5,72 @@ import ( "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" abci "github.com/tendermint/tendermint/abci/types" - "github.com/akash-network/node/x/audit/keeper" - types "github.com/akash-network/akash-api/go/node/audit/v1beta3" + + "github.com/akash-network/node/x/audit/keeper" ) -// ValidateGenesis does validation check of the Genesis and returns error incase of failure +// ValidateGenesis does validation check of the Genesis and returns error in case of a failure func ValidateGenesis(data *types.GenesisState) error { + for _, record := range data.Attributes { + if _, err := sdk.AccAddressFromBech32(record.Owner); err != nil { + return sdkerrors.ErrInvalidAddress.Wrap("audited attributes: invalid owner address") + } + + if _, err := sdk.AccAddressFromBech32(record.Auditor); err != nil { + return sdkerrors.ErrInvalidAddress.Wrap("audited attributes: invalid auditor address") + } + + if err := record.Attributes.Validate(); err != nil { + sdkerrors.Wrap(err, "audited attributes: invalid attributes") + } + } + return nil } // InitGenesis initiate genesis state and return updated validator details func InitGenesis(ctx sdk.Context, keeper keeper.Keeper, data *types.GenesisState) []abci.ValidatorUpdate { + for _, record := range data.Attributes { + owner, err := sdk.AccAddressFromBech32(record.Owner) + + if err != nil { + panic(sdkerrors.ErrInvalidAddress.Wrap("audited attributes: invalid owner address").Error()) + } + + auditor, err := sdk.AccAddressFromBech32(record.Auditor) + if err != nil { + panic(sdkerrors.ErrInvalidAddress.Wrap("audited attributes: invalid auditor address")) + } + + err = keeper.CreateOrUpdateProviderAttributes(ctx, types.ProviderID{ + Owner: owner, + Auditor: auditor, + }, record.Attributes) + if err != nil { + panic(sdkerrors.Wrap(err, "unable to init genesis with provider")) + } + } + return []abci.ValidatorUpdate{} } // ExportGenesis returns genesis state as raw bytes for the provider module func ExportGenesis(ctx sdk.Context, k keeper.Keeper) *types.GenesisState { + var attr []types.AuditedAttributes + + k.WithProviders(ctx, func(provider types.Provider) bool { + attr = append(attr, types.AuditedAttributes{ + Owner: provider.Owner, + Auditor: provider.Auditor, + Attributes: provider.Attributes.Dup(), + }) + return false + }) + return &types.GenesisState{} } diff --git a/x/cert/genesis.go b/x/cert/genesis.go index 9819415b63..e2ffa68fc2 100644 --- a/x/cert/genesis.go +++ b/x/cert/genesis.go @@ -1,7 +1,9 @@ package cert import ( + "crypto/x509" "encoding/json" + "encoding/pem" "fmt" "github.com/cosmos/cosmos-sdk/codec" @@ -42,6 +44,31 @@ func InitGenesis(ctx sdk.Context, keeper keeper.Keeper, data *types.GenesisState // ExportGenesis returns genesis state as raw bytes for the provider module func ExportGenesis(ctx sdk.Context, k keeper.Keeper) *types.GenesisState { + var res types.GenesisCertificates + + k.WithCertificates1(ctx, func(id types.CertID, certificate types.CertificateResponse) bool { + block, rest := pem.Decode(certificate.Certificate.Cert) + if len(rest) > 0 { + panic(fmt.Sprintf("unable to decode certificate")) + } + + cert, err := x509.ParseCertificate(block.Bytes) + if err != nil { + panic(err.Error()) + } + + if cert.SerialNumber.String() != id.Serial.String() { + panic(fmt.Sprintf("certificate id does not match")) + } + + res = append(res, types.GenesisCertificate{ + Owner: id.Owner.String(), + Certificate: certificate.Certificate, + }) + + return false + }) + return &types.GenesisState{} } diff --git a/x/cert/keeper/keeper.go b/x/cert/keeper/keeper.go index ed11117586..fdc7c25606 100644 --- a/x/cert/keeper/keeper.go +++ b/x/cert/keeper/keeper.go @@ -16,6 +16,7 @@ type Keeper interface { RevokeCertificate(sdk.Context, types.CertID) error GetCertificateByID(ctx sdk.Context, id types.CertID) (types.CertificateResponse, bool) WithCertificates(ctx sdk.Context, fn func(certificate types.CertificateResponse) bool) + WithCertificates1(ctx sdk.Context, fn func(id types.CertID, certificate types.CertificateResponse) bool) WithCertificatesState(ctx sdk.Context, state types.Certificate_State, fn func(certificate types.CertificateResponse) bool) WithOwner(ctx sdk.Context, id sdk.Address, fn func(types.CertificateResponse) bool) WithOwnerState(ctx sdk.Context, id sdk.Address, state types.Certificate_State, fn func(types.CertificateResponse) bool) @@ -134,6 +135,28 @@ func (k keeper) WithCertificates(ctx sdk.Context, fn func(certificate types.Cert } } +// WithCertificates1 iterates all certificates +func (k keeper) WithCertificates1(ctx sdk.Context, fn func(id types.CertID, certificate types.CertificateResponse) bool) { + store := ctx.KVStore(k.skey) + iter := store.Iterator(nil, nil) + + defer func() { + _ = iter.Close() + }() + + for ; iter.Valid(); iter.Next() { + id, err := parseCertID(iter.Key()) + if err != nil { + panic(err.Error()) + } + + item := k.mustUnmarshal(iter.Key(), iter.Value()) + if stop := fn(id, item); stop { + break + } + } +} + // WithCertificatesState iterates all certificates in certain state func (k keeper) WithCertificatesState(ctx sdk.Context, state types.Certificate_State, fn func(certificate types.CertificateResponse) bool) { store := ctx.KVStore(k.skey) diff --git a/x/cert/keeper/key.go b/x/cert/keeper/key.go index dae2b02a14..b75ccefade 100644 --- a/x/cert/keeper/key.go +++ b/x/cert/keeper/key.go @@ -50,3 +50,28 @@ func certificateSerialFromKey(key []byte) big.Int { return *new(big.Int).SetBytes(key[keyAddrPrefixLen+addrLen:]) } + +func parseCertID(from []byte) (types.CertID, error) { + res := types.CertID{ + Serial: *big.NewInt(0), + } + + // first byte is prefix id. skip it + from = from[1:] + addLen := from[0] + + from = from[1:] + + addr := from[:addLen-1] + serial := from[addLen:] + + err := sdk.VerifyAddressFormat(addr) + if err != nil { + return res, err + } + + res.Owner = sdk.AccAddress(addr) + res.Serial.SetBytes(serial) + + return res, nil +}