Skip to content
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

Revert "feat(dot/rpc) implement author_hasSessionKeys RPC call" #1714

Merged
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
10 changes: 0 additions & 10 deletions dot/core/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -461,16 +461,6 @@ func (s *Service) HasKey(pubKeyStr, keyType string) (bool, error) {
return keystore.HasKey(pubKeyStr, keyType, s.keys.Acco)
}

// DecodeSessionKeys executes the runtime DecodeSessionKeys and return the scale encoded keys
func (s *Service) DecodeSessionKeys(enc []byte) ([]byte, error) {
rt, err := s.blockState.GetRuntime(nil)
if err != nil {
return nil, err
}

return rt.DecodeSessionKeys(enc)
}

// GetRuntimeVersion gets the current RuntimeVersion
func (s *Service) GetRuntimeVersion(bhash *common.Hash) (runtime.Version, error) {
var stateRootHash *common.Hash
Expand Down
16 changes: 9 additions & 7 deletions dot/rpc/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -233,13 +233,15 @@ func (h *HTTPServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
// NewWSConn to create new WebSocket Connection struct
func NewWSConn(conn *websocket.Conn, cfg *HTTPServerConfig) *subscription.WSConn {
c := &subscription.WSConn{
Wsconn: conn,
Subscriptions: make(map[uint32]subscription.Listener),
StorageAPI: cfg.StorageAPI,
BlockAPI: cfg.BlockAPI,
CoreAPI: cfg.CoreAPI,
TxStateAPI: cfg.TransactionQueueAPI,
RPCHost: fmt.Sprintf("http://%s:%d/", cfg.Host, cfg.RPCPort),
Wsconn: conn,
Subscriptions: make(map[uint]subscription.Listener),
BlockSubChannels: make(map[uint]byte),
StorageSubChannels: make(map[int]byte),
StorageAPI: cfg.StorageAPI,
BlockAPI: cfg.BlockAPI,
CoreAPI: cfg.CoreAPI,
TxStateAPI: cfg.TransactionQueueAPI,
RPCHost: fmt.Sprintf("http://%s:%d/", cfg.Host, cfg.RPCPort),
HTTP: &http.Client{
Timeout: time.Second * 30,
},
Expand Down
1 change: 0 additions & 1 deletion dot/rpc/modules/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,6 @@ type CoreAPI interface {
GetRuntimeVersion(bhash *common.Hash) (runtime.Version, error)
HandleSubmittedExtrinsic(types.Extrinsic) error
GetMetadata(bhash *common.Hash) ([]byte, error)
DecodeSessionKeys(enc []byte) ([]byte, error)
}

// RPCAPI is the interface for methods related to RPC service
Expand Down
83 changes: 11 additions & 72 deletions dot/rpc/modules/author.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,13 @@
package modules

import (
"errors"
"fmt"
"net/http"
"strings"
"reflect"

"github.com/ChainSafe/gossamer/dot/types"
"github.com/ChainSafe/gossamer/lib/common"
"github.com/ChainSafe/gossamer/lib/keystore"
"github.com/ChainSafe/gossamer/pkg/scale"

log "github.com/ChainSafe/log15"
)
Expand All @@ -36,17 +35,8 @@ type AuthorModule struct {
txStateAPI TransactionStateAPI
}

// HasSessionKeyRequest is used to receive the rpc data
type HasSessionKeyRequest struct {
PublicKeys string
}

// KeyInsertRequest is used as model for the JSON
type KeyInsertRequest struct {
Type string
Seed string
PublicKey string
}
type KeyInsertRequest []string

// Extrinsic represents a hex-encoded extrinsic
type Extrinsic struct {
Expand Down Expand Up @@ -74,18 +64,6 @@ type RemoveExtrinsicsResponse []common.Hash
// KeyRotateResponse is a byte array used to rotate
type KeyRotateResponse []byte

// HasSessionKeyResponse is the response to the RPC call author_hasSessionKeys
type HasSessionKeyResponse bool

// KeyTypeID represents the key type of a session key
type keyTypeID [4]uint8

// DecodedKey is the representation of a scaled decoded public key
type decodedKey struct {
Data []uint8
Type keyTypeID
}

// ExtrinsicStatus holds the actual valid statuses
type ExtrinsicStatus struct {
IsFuture bool
Expand Down Expand Up @@ -116,66 +94,27 @@ func NewAuthorModule(logger log.Logger, coreAPI CoreAPI, txStateAPI TransactionS
}
}

// HasSessionKeys checks if the keystore has private keys for the given session public keys.
func (am *AuthorModule) HasSessionKeys(r *http.Request, req *HasSessionKeyRequest, res *HasSessionKeyResponse) error {
pubKeysBytes, err := common.HexToBytes(req.PublicKeys)
if err != nil {
return err
}

pkeys, err := scale.Marshal(pubKeysBytes)
if err != nil {
return err
}

data, err := am.coreAPI.DecodeSessionKeys(pkeys)
if err != nil {
*res = false
return err
}
// InsertKey inserts a key into the keystore
func (am *AuthorModule) InsertKey(r *http.Request, req *KeyInsertRequest, res *KeyInsertResponse) error {
keyReq := *req

var decodedKeys *[]decodedKey
err = scale.Unmarshal(data, &decodedKeys)
pkDec, err := common.HexToBytes(keyReq[1])
if err != nil {
return err
}

if decodedKeys == nil || len(*decodedKeys) < 1 {
*res = false
return nil
}

for _, key := range *decodedKeys {
encType := keystore.Name(key.Type[:])
ok, err := am.coreAPI.HasKey(common.BytesToHex(key.Data), string(encType))

if err != nil || !ok {
*res = false
return err
}
}

*res = true
return nil
}

// InsertKey inserts a key into the keystore
func (am *AuthorModule) InsertKey(r *http.Request, req *KeyInsertRequest, res *KeyInsertResponse) error {
keyReq := *req

keyBytes, err := common.HexToBytes(req.Seed)
privateKey, err := keystore.DecodePrivateKey(pkDec, keystore.DetermineKeyType(keyReq[0]))
if err != nil {
return err
}

keyPair, err := keystore.DecodeKeyPairFromHex(keyBytes, keystore.DetermineKeyType(keyReq.Type))
keyPair, err := keystore.PrivateKeyToKeypair(privateKey)
if err != nil {
return err
}

//strings.EqualFold compare using case-insensitivity.
if !strings.EqualFold(keyPair.Public().Hex(), keyReq.PublicKey) {
return errors.New("generated public key does not equal provide public key")
if !reflect.DeepEqual(keyPair.Public().Hex(), keyReq[2]) {
return fmt.Errorf("generated public key does not equal provide public key")
}

am.coreAPI.InsertKey(keyPair)
Expand Down
74 changes: 4 additions & 70 deletions dot/rpc/modules/author_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,78 +8,13 @@ import (
apimocks "github.com/ChainSafe/gossamer/dot/rpc/modules/mocks"
"github.com/ChainSafe/gossamer/dot/types"
"github.com/ChainSafe/gossamer/lib/common"
"github.com/ChainSafe/gossamer/lib/crypto/sr25519"
"github.com/ChainSafe/gossamer/lib/keystore"
"github.com/ChainSafe/gossamer/lib/runtime"
"github.com/ChainSafe/gossamer/lib/runtime/wasmer"
"github.com/ChainSafe/gossamer/lib/transaction"
log "github.com/ChainSafe/log15"
"github.com/google/go-cmp/cmp"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
)

func TestAuthorModule_HasSessionKey(t *testing.T) {
globalStore := keystore.NewGlobalKeystore()

coremockapi := new(apimocks.MockCoreAPI)
mockInsertKey := coremockapi.On("InsertKey", mock.AnythingOfType("*sr25519.Keypair"))
mockInsertKey.Run(func(args mock.Arguments) {
kp := args.Get(0).(*sr25519.Keypair)
globalStore.Acco.Insert(kp)
})

mockHasKey := coremockapi.On("HasKey", mock.AnythingOfType("string"), mock.AnythingOfType("string"))
mockHasKey.Run(func(args mock.Arguments) {
pubKeyHex := args.Get(0).(string)
keyType := args.Get(1).(string)

ok, err := keystore.HasKey(pubKeyHex, keyType, globalStore.Acco)
mockHasKey.ReturnArguments = []interface{}{ok, err}
})

keys := "0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d34309a9d2a24213896ff06895db16aade8b6502f3a71cf56374cc3852042602634309a9d2a24213896ff06895db16aade8b6502f3a71cf56374cc3852042602634309a9d2a24213896ff06895db16aade8b6502f3a71cf56374cc38520426026"
runtimeInstance := wasmer.NewTestInstance(t, runtime.NODE_RUNTIME)

decodeSessionKeysMock := coremockapi.On("DecodeSessionKeys", mock.AnythingOfType("[]uint8"))
decodeSessionKeysMock.Run(func(args mock.Arguments) {
b := args.Get(0).([]byte)
dec, err := runtimeInstance.DecodeSessionKeys(b)
decodeSessionKeysMock.ReturnArguments = []interface{}{dec, err}
})

module := &AuthorModule{
coreAPI: coremockapi,
logger: log.New("service", "RPC", "module", "author"),
}

req := &HasSessionKeyRequest{
PublicKeys: keys,
}

err := module.InsertKey(nil, &KeyInsertRequest{
Type: "babe",
Seed: "0xfec0f475b818470af5caf1f3c1b1558729961161946d581d2755f9fb566534f8",
PublicKey: "0x34309a9d2a24213896ff06895db16aade8b6502f3a71cf56374cc38520426026",
}, nil)
coremockapi.AssertCalled(t, "InsertKey", mock.AnythingOfType("*sr25519.Keypair"))
require.NoError(t, err)
require.Equal(t, 1, globalStore.Acco.Size())

err = module.InsertKey(nil, &KeyInsertRequest{
Type: "babe",
Seed: "0xe5be9a5092b81bca64be81d212e7f2f9eba183bb7a90954f7b76361f6edb5c0a",
PublicKey: "0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d",
}, nil)
require.NoError(t, err)
require.Equal(t, 2, globalStore.Acco.Size())

var res HasSessionKeyResponse
err = module.HasSessionKeys(nil, req, &res)
require.NoError(t, err)
require.True(t, bool(res))
}

func TestAuthorModule_SubmitExtrinsic(t *testing.T) {
errMockCoreAPI := &apimocks.MockCoreAPI{}
errMockCoreAPI.On("HandleSubmittedExtrinsic", mock.AnythingOfType("types.Extrinsic")).Return(fmt.Errorf("some error"))
Expand Down Expand Up @@ -267,8 +202,8 @@ func TestAuthorModule_InsertKey(t *testing.T) {
args: args{
req: &KeyInsertRequest{
"babe",
"0xb7e9185065667390d2ad952a5324e8c365c9bf503dcf97c67a5ce861afe97309",
"0x6246ddf254e0b4b4e7dffefc8adf69d212b98ac2b579c362b473fec8c40b4c0a",
"0xdad5131003242c37c227f744f82118dd59a24b949ae264a93d949100738c196c",
},
},
},
Expand All @@ -279,10 +214,9 @@ func TestAuthorModule_InsertKey(t *testing.T) {
coreAPI: mockCoreAPI,
},
args: args{
req: &KeyInsertRequest{
"gran",
"0xb48004c6e1625282313b07d1c9950935e86894a2e4f21fb1ffee9854d180c781",
"0xa7d6507d59f8871b8f1a0f2c32e219adfacff4c9fcb05b0b2d8ebd6a65c88ee6",
req: &KeyInsertRequest{"gran",
"0xb7e9185065667390d2ad952a5324e8c365c9bf503dcf97c67a5ce861afe97309b7e9185065667390d2ad952a5324e8c365c9bf503dcf97c67a5ce861afe97309",
"0xb7e9185065667390d2ad952a5324e8c365c9bf503dcf97c67a5ce861afe97309",
},
},
},
Expand Down
37 changes: 14 additions & 23 deletions dot/rpc/modules/mocks/core_api.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion dot/rpc/service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ func TestNewService(t *testing.T) {
func TestService_Methods(t *testing.T) {
qtySystemMethods := 13
qtyRPCMethods := 1
qtyAuthorMethods := 8
qtyAuthorMethods := 7

rpcService := NewService()
sysMod := modules.NewSystemModule(nil, nil, nil, nil, nil, nil)
Expand Down
Loading