mirror of
https://github.com/planetmint/planetmint-go.git
synced 2025-06-03 20:56:38 +00:00
implemented notarize asset with secp256k1 validation
Signed-off-by: Lorenz Herzberger <lorenzherzberger@gmail.com>
This commit is contained in:
parent
8ba1306f2e
commit
f5de5d4327
@ -3,6 +3,12 @@ package keeper
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"planetmint-go/testutil/sample"
|
||||
"planetmint-go/x/asset/keeper"
|
||||
"planetmint-go/x/asset/types"
|
||||
|
||||
assettestutils "planetmint-go/x/asset/testutil"
|
||||
|
||||
tmdb "github.com/cometbft/cometbft-db"
|
||||
"github.com/cometbft/cometbft/libs/log"
|
||||
tmproto "github.com/cometbft/cometbft/proto/tendermint/types"
|
||||
@ -12,9 +18,8 @@ import (
|
||||
storetypes "github.com/cosmos/cosmos-sdk/store/types"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
typesparams "github.com/cosmos/cosmos-sdk/x/params/types"
|
||||
"github.com/golang/mock/gomock"
|
||||
"github.com/stretchr/testify/require"
|
||||
"planetmint-go/x/asset/keeper"
|
||||
"planetmint-go/x/asset/types"
|
||||
)
|
||||
|
||||
func AssetKeeper(t testing.TB) (*keeper.Keeper, sdk.Context) {
|
||||
@ -25,6 +30,7 @@ func AssetKeeper(t testing.TB) (*keeper.Keeper, sdk.Context) {
|
||||
stateStore := store.NewCommitMultiStore(db)
|
||||
stateStore.MountStoreWithDB(storeKey, storetypes.StoreTypeIAVL, db)
|
||||
stateStore.MountStoreWithDB(memStoreKey, storetypes.StoreTypeMemory, nil)
|
||||
|
||||
require.NoError(t, stateStore.LoadLatestVersion())
|
||||
|
||||
registry := codectypes.NewInterfaceRegistry()
|
||||
@ -36,16 +42,26 @@ func AssetKeeper(t testing.TB) (*keeper.Keeper, sdk.Context) {
|
||||
memStoreKey,
|
||||
"AssetParams",
|
||||
)
|
||||
|
||||
ctx := sdk.NewContext(stateStore, tmproto.Header{}, false, log.NewNopLogger())
|
||||
|
||||
ctrl := gomock.NewController(t)
|
||||
mk := assettestutils.NewMockMachineKeeper(ctrl)
|
||||
sk, pk := sample.KeyPair()
|
||||
id := sample.MachineIndex(pk, pk, pk)
|
||||
mk.EXPECT().GetMachineIndex(ctx, pk).Return(id, true).AnyTimes()
|
||||
mk.EXPECT().GetMachineIndex(ctx, sk).Return(id, false).AnyTimes()
|
||||
mk.EXPECT().GetMachine(ctx, id).Return(sample.Machine(pk, pk, pk), true).AnyTimes()
|
||||
mk.EXPECT().GetMachine(ctx, sk).Return(sample.Machine(pk, pk, pk), false).AnyTimes()
|
||||
|
||||
k := keeper.NewKeeper(
|
||||
cdc,
|
||||
storeKey,
|
||||
memStoreKey,
|
||||
paramsSubspace,
|
||||
nil,
|
||||
mk,
|
||||
)
|
||||
|
||||
ctx := sdk.NewContext(stateStore, tmproto.Header{}, false, log.NewNopLogger())
|
||||
|
||||
// Initialize params
|
||||
k.SetParams(ctx, types.DefaultParams())
|
||||
|
||||
|
@ -2,16 +2,55 @@ package keeper
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"planetmint-go/x/asset/types"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
)
|
||||
|
||||
func (k msgServer) NotarizeAsset(goCtx context.Context, msg *types.MsgNotarizeAsset) (*types.MsgNotarizeAssetResponse, error) {
|
||||
ctx := sdk.UnwrapSDKContext(goCtx)
|
||||
|
||||
// TODO: Handling the message
|
||||
_ = ctx
|
||||
_, found := k.machineKeeper.GetMachineIndex(ctx, msg.PubKey)
|
||||
|
||||
if !found {
|
||||
return &types.MsgNotarizeAssetResponse{}, errors.New("machine not found")
|
||||
}
|
||||
|
||||
valid := ValidateSignature(msg.Hash, msg.Signature, msg.PubKey)
|
||||
if !valid {
|
||||
return &types.MsgNotarizeAssetResponse{}, errors.New("invalid signature")
|
||||
}
|
||||
|
||||
var asset = types.Asset{
|
||||
Hash: msg.Hash,
|
||||
Signature: msg.Signature,
|
||||
Pubkey: msg.PubKey,
|
||||
}
|
||||
|
||||
k.StoreAsset(ctx, asset)
|
||||
|
||||
return &types.MsgNotarizeAssetResponse{}, nil
|
||||
}
|
||||
|
||||
func ValidateSignature(message string, signature string, publicKey string) bool {
|
||||
// Convert the message, signature, and public key from hex to bytes
|
||||
messageBytes, _ := hex.DecodeString(message)
|
||||
signatureBytes, _ := hex.DecodeString(signature)
|
||||
publicKeyBytes, _ := hex.DecodeString(publicKey)
|
||||
|
||||
// Hash the message
|
||||
hash := sha256.Sum256(messageBytes)
|
||||
|
||||
// Create a secp256k1 public key object
|
||||
pubKey := &secp256k1.PubKey{Key: publicKeyBytes}
|
||||
|
||||
// Verify the signature
|
||||
isValid := pubKey.VerifySignature(hash[:], signatureBytes)
|
||||
|
||||
return isValid
|
||||
}
|
||||
|
@ -2,13 +2,19 @@ package keeper_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"testing"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/stretchr/testify/require"
|
||||
keepertest "planetmint-go/testutil/keeper"
|
||||
"planetmint-go/testutil/sample"
|
||||
"planetmint-go/x/asset/keeper"
|
||||
"planetmint-go/x/asset/types"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func setupMsgServer(t testing.TB) (types.MsgServer, context.Context) {
|
||||
@ -21,3 +27,47 @@ func TestMsgServer(t *testing.T) {
|
||||
require.NotNil(t, ms)
|
||||
require.NotNil(t, ctx)
|
||||
}
|
||||
|
||||
func TestMsgServerNotarizeAsset(t *testing.T) {
|
||||
sk, pk := sample.KeyPair()
|
||||
cid := "cid"
|
||||
|
||||
skBytes, err := hex.DecodeString(sk)
|
||||
if err != nil {
|
||||
assert.Equal(t, true, false)
|
||||
}
|
||||
privKey := &secp256k1.PrivKey{Key: skBytes}
|
||||
|
||||
cidBytes, _ := hex.DecodeString(cid)
|
||||
hash := sha256.Sum256(cidBytes)
|
||||
|
||||
sign, err := privKey.Sign(hash[:])
|
||||
if err != nil {
|
||||
assert.Equal(t, true, false)
|
||||
}
|
||||
|
||||
signatureHex := hex.EncodeToString(sign)
|
||||
|
||||
msg := types.NewMsgNotarizeAsset(pk, cid, signatureHex, pk)
|
||||
msgServer, ctx := setupMsgServer(t)
|
||||
res, err := msgServer.NotarizeAsset(ctx, msg)
|
||||
if assert.NoError(t, err) {
|
||||
assert.Equal(t, &types.MsgNotarizeAssetResponse{}, res)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMsgServerNotarizeAssetMachineNotFound(t *testing.T) {
|
||||
sk, _ := sample.KeyPair()
|
||||
msg := types.NewMsgNotarizeAsset(sk, "cid", "sign", sk)
|
||||
msgServer, ctx := setupMsgServer(t)
|
||||
_, err := msgServer.NotarizeAsset(ctx, msg)
|
||||
assert.EqualError(t, err, "machine not found")
|
||||
}
|
||||
|
||||
func TestMsgServerNotarizeAssetInvalidAsset(t *testing.T) {
|
||||
_, pk := sample.KeyPair()
|
||||
msg := types.NewMsgNotarizeAsset(pk, "cid", "sign", pk)
|
||||
msgServer, ctx := setupMsgServer(t)
|
||||
_, err := msgServer.NotarizeAsset(ctx, msg)
|
||||
assert.EqualError(t, err, "invalid signature")
|
||||
}
|
||||
|
141
x/asset/testutil/expected_keepers_mock.go
Normal file
141
x/asset/testutil/expected_keepers_mock.go
Normal file
@ -0,0 +1,141 @@
|
||||
// Code generated by MockGen. DO NOT EDIT.
|
||||
// Source: x/asset/types/expected_keepers.go
|
||||
|
||||
// Package testutil is a generated GoMock package.
|
||||
package testutil
|
||||
|
||||
import (
|
||||
types1 "planetmint-go/x/machine/types"
|
||||
reflect "reflect"
|
||||
|
||||
types "github.com/cosmos/cosmos-sdk/types"
|
||||
types0 "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
gomock "github.com/golang/mock/gomock"
|
||||
)
|
||||
|
||||
// MockAccountKeeper is a mock of AccountKeeper interface.
|
||||
type MockAccountKeeper struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockAccountKeeperMockRecorder
|
||||
}
|
||||
|
||||
// MockAccountKeeperMockRecorder is the mock recorder for MockAccountKeeper.
|
||||
type MockAccountKeeperMockRecorder struct {
|
||||
mock *MockAccountKeeper
|
||||
}
|
||||
|
||||
// NewMockAccountKeeper creates a new mock instance.
|
||||
func NewMockAccountKeeper(ctrl *gomock.Controller) *MockAccountKeeper {
|
||||
mock := &MockAccountKeeper{ctrl: ctrl}
|
||||
mock.recorder = &MockAccountKeeperMockRecorder{mock}
|
||||
return mock
|
||||
}
|
||||
|
||||
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||
func (m *MockAccountKeeper) EXPECT() *MockAccountKeeperMockRecorder {
|
||||
return m.recorder
|
||||
}
|
||||
|
||||
// GetAccount mocks base method.
|
||||
func (m *MockAccountKeeper) GetAccount(ctx types.Context, addr types.AccAddress) types0.AccountI {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetAccount", ctx, addr)
|
||||
ret0, _ := ret[0].(types0.AccountI)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// GetAccount indicates an expected call of GetAccount.
|
||||
func (mr *MockAccountKeeperMockRecorder) GetAccount(ctx, addr interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetAccount", reflect.TypeOf((*MockAccountKeeper)(nil).GetAccount), ctx, addr)
|
||||
}
|
||||
|
||||
// MockBankKeeper is a mock of BankKeeper interface.
|
||||
type MockBankKeeper struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockBankKeeperMockRecorder
|
||||
}
|
||||
|
||||
// MockBankKeeperMockRecorder is the mock recorder for MockBankKeeper.
|
||||
type MockBankKeeperMockRecorder struct {
|
||||
mock *MockBankKeeper
|
||||
}
|
||||
|
||||
// NewMockBankKeeper creates a new mock instance.
|
||||
func NewMockBankKeeper(ctrl *gomock.Controller) *MockBankKeeper {
|
||||
mock := &MockBankKeeper{ctrl: ctrl}
|
||||
mock.recorder = &MockBankKeeperMockRecorder{mock}
|
||||
return mock
|
||||
}
|
||||
|
||||
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||
func (m *MockBankKeeper) EXPECT() *MockBankKeeperMockRecorder {
|
||||
return m.recorder
|
||||
}
|
||||
|
||||
// SpendableCoins mocks base method.
|
||||
func (m *MockBankKeeper) SpendableCoins(ctx types.Context, addr types.AccAddress) types.Coins {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "SpendableCoins", ctx, addr)
|
||||
ret0, _ := ret[0].(types.Coins)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// SpendableCoins indicates an expected call of SpendableCoins.
|
||||
func (mr *MockBankKeeperMockRecorder) SpendableCoins(ctx, addr interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SpendableCoins", reflect.TypeOf((*MockBankKeeper)(nil).SpendableCoins), ctx, addr)
|
||||
}
|
||||
|
||||
// MockMachineKeeper is a mock of MachineKeeper interface.
|
||||
type MockMachineKeeper struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockMachineKeeperMockRecorder
|
||||
}
|
||||
|
||||
// MockMachineKeeperMockRecorder is the mock recorder for MockMachineKeeper.
|
||||
type MockMachineKeeperMockRecorder struct {
|
||||
mock *MockMachineKeeper
|
||||
}
|
||||
|
||||
// NewMockMachineKeeper creates a new mock instance.
|
||||
func NewMockMachineKeeper(ctrl *gomock.Controller) *MockMachineKeeper {
|
||||
mock := &MockMachineKeeper{ctrl: ctrl}
|
||||
mock.recorder = &MockMachineKeeperMockRecorder{mock}
|
||||
return mock
|
||||
}
|
||||
|
||||
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||
func (m *MockMachineKeeper) EXPECT() *MockMachineKeeperMockRecorder {
|
||||
return m.recorder
|
||||
}
|
||||
|
||||
// GetMachine mocks base method.
|
||||
func (m *MockMachineKeeper) GetMachine(ctx types.Context, index types1.MachineIndex) (types1.Machine, bool) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetMachine", ctx, index)
|
||||
ret0, _ := ret[0].(types1.Machine)
|
||||
ret1, _ := ret[1].(bool)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// GetMachine indicates an expected call of GetMachine.
|
||||
func (mr *MockMachineKeeperMockRecorder) GetMachine(ctx, index interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetMachine", reflect.TypeOf((*MockMachineKeeper)(nil).GetMachine), ctx, index)
|
||||
}
|
||||
|
||||
// GetMachineIndex mocks base method.
|
||||
func (m *MockMachineKeeper) GetMachineIndex(ctx types.Context, pubKey string) (types1.MachineIndex, bool) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetMachineIndex", ctx, pubKey)
|
||||
ret0, _ := ret[0].(types1.MachineIndex)
|
||||
ret1, _ := ret[1].(bool)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// GetMachineIndex indicates an expected call of GetMachineIndex.
|
||||
func (mr *MockMachineKeeperMockRecorder) GetMachineIndex(ctx, pubKey interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetMachineIndex", reflect.TypeOf((*MockMachineKeeper)(nil).GetMachineIndex), ctx, pubKey)
|
||||
}
|
@ -1,12 +1,16 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
machinetypes "planetmint-go/x/machine/types"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
)
|
||||
|
||||
type MachineKeeper interface {
|
||||
// Methods imported from machine should be defined here
|
||||
GetMachine(ctx sdk.Context, index machinetypes.MachineIndex) (val machinetypes.Machine, found bool)
|
||||
GetMachineIndex(ctx sdk.Context, pubKey string) (val machinetypes.MachineIndex, found bool)
|
||||
}
|
||||
|
||||
// AccountKeeper defines the expected account keeper used for simulations (noalias)
|
||||
|
Loading…
x
Reference in New Issue
Block a user