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

feat(dot/rpc) implement author_hasSessionKeys RPC call #1715

Merged
merged 94 commits into from
Aug 6, 2021
Merged
Show file tree
Hide file tree
Changes from 87 commits
Commits
Show all changes
94 commits
Select commit Hold shift + click to select a range
fdac471
chore: add interface for grandpa in rpc pkg
EclesioMeloJunior Jun 29, 2021
888de1f
chore: create roundState rpc call
EclesioMeloJunior Jun 29, 2021
157d3fd
chore: coment unused branch
EclesioMeloJunior Jun 29, 2021
904dbde
chore: fix lint
EclesioMeloJunior Jun 29, 2021
fc77c6d
Merge branch 'development' into eclesio/grandpa-roundState-rpc
EclesioMeloJunior Jun 29, 2021
feefdb2
Merge branch 'development' into eclesio/grandpa-roundState-rpc
EclesioMeloJunior Jun 30, 2021
6fad347
chore: add test case
EclesioMeloJunior Jul 1, 2021
3b41f90
Merge branch 'eclesio/grandpa-roundState-rpc' of github.com:ChainSafe…
EclesioMeloJunior Jul 1, 2021
ff811b1
chore: fix lint
EclesioMeloJunior Jul 1, 2021
04eb2e8
Merge branch 'eclesio/grandpa-roundState-rpc' into eclesio/subscribe-…
EclesioMeloJunior Jul 3, 2021
22b1b80
chore: add grandpa subscribe justification rpc call
EclesioMeloJunior Jul 3, 2021
8eb3b5e
chore: add cancel function to stop goroutine when unsuubscribe
EclesioMeloJunior Jul 3, 2021
6d20c6d
chore: resolve lint
EclesioMeloJunior Jul 5, 2021
09b70bc
chore: add tests to subscribe justification call
EclesioMeloJunior Jul 5, 2021
1486165
Merge branch 'development' into eclesio/subscribe-justification-rpc
EclesioMeloJunior Jul 5, 2021
c3d6f55
Merge branch 'development' into eclesio/subscribe-justification-rpc
EclesioMeloJunior Jul 6, 2021
6e32d71
chore: minor changes
EclesioMeloJunior Jul 7, 2021
d19b6ac
resolve conflicts
EclesioMeloJunior Jul 7, 2021
bab92a0
remove deps from round state rpc call pr
EclesioMeloJunior Jul 7, 2021
edd2f39
chore: remove unecessary changes
EclesioMeloJunior Jul 7, 2021
8aa968c
remove inpackage well mock is in mocks folder
EclesioMeloJunior Jul 7, 2021
da2fc08
chore: fix lint
EclesioMeloJunior Jul 7, 2021
52647bd
Merge branch 'development' into eclesio/subscribe-justification-rpc
EclesioMeloJunior Jul 8, 2021
6f28204
wip: fixing tests
EclesioMeloJunior Jul 8, 2021
09408fd
chore: use channels to control goroutines
EclesioMeloJunior Jul 8, 2021
542f853
Merge branch 'development' into eclesio/subscribe-justification-rpc
EclesioMeloJunior Jul 8, 2021
fecd636
chore: resolve lint
EclesioMeloJunior Jul 8, 2021
dc4b83d
Merge branch 'development' into eclesio/subscribe-justification-rpc
arijitAD Jul 9, 2021
83617bb
Merge branch 'development' into eclesio/subscribe-justification-rpc
EclesioMeloJunior Jul 9, 2021
a7a9846
chore: resolve conflicts
EclesioMeloJunior Jul 12, 2021
4f51ed8
add time.Duration on structs
EclesioMeloJunior Jul 12, 2021
eca7401
Merge branch 'development' into eclesio/subscribe-justification-rpc
EclesioMeloJunior Jul 12, 2021
b1968fa
Merge branch 'development' into eclesio/subscribe-justification-rpc
EclesioMeloJunior Jul 14, 2021
215f868
chore: add runtime method and rpc method
EclesioMeloJunior Jul 19, 2021
aee10f1
wip: fix runtime response scale decoding
EclesioMeloJunior Jul 21, 2021
f6d4640
chore: adding data to tests
EclesioMeloJunior Jul 21, 2021
85c8a81
wip: improve test coverage and assertions
EclesioMeloJunior Jul 21, 2021
70439a5
chore: hasSessionKey rpc call done
EclesioMeloJunior Jul 22, 2021
e0d9f6c
Merge branch 'development' into eclesio/rpc-has-session-keys
EclesioMeloJunior Jul 23, 2021
444b03a
chore: change config.toml back
EclesioMeloJunior Jul 23, 2021
6dfdf15
chore: remove log, add string.EqualFold
EclesioMeloJunior Jul 23, 2021
fe70b02
chore: remove unused logs, get back new private key
EclesioMeloJunior Jul 23, 2021
8a65889
update hasSessionKey method to use coreapi insted of runtime api
EclesioMeloJunior Jul 23, 2021
7fc851c
Merge branch 'development' into eclesio/rpc-has-session-keys
EclesioMeloJunior Jul 23, 2021
3d6fa1c
chore: update confligts with development branch
EclesioMeloJunior Jul 23, 2021
145e6d0
Merge branch 'development' into eclesio/rpc-has-session-keys
EclesioMeloJunior Jul 23, 2021
1f84625
chore: resolve lint issues
EclesioMeloJunior Jul 23, 2021
b433e80
Merge branch 'eclesio/rpc-has-session-keys' of github.com:ChainSafe/g…
EclesioMeloJunior Jul 23, 2021
878abed
chore: change from []byte to []uint8
EclesioMeloJunior Jul 23, 2021
f167333
Merge branch 'development' into eclesio/rpc-has-session-keys
EclesioMeloJunior Jul 24, 2021
8c833d7
chore: fix tests failures
EclesioMeloJunior Jul 26, 2021
1079926
Merge branch 'eclesio/rpc-has-session-keys' of github.com:ChainSafe/g…
EclesioMeloJunior Jul 26, 2021
38f5229
Merge branch 'development' into eclesio/subscribe-justification-rpc
EclesioMeloJunior Jul 26, 2021
d867db8
chore: fix HasSessionKeyResponse comments
EclesioMeloJunior Jul 26, 2021
05cb9f4
chore: fix KeyTypeID comments
EclesioMeloJunior Jul 26, 2021
32ab688
chore: update comments, unexport struct and remove qtyCheck
EclesioMeloJunior Jul 26, 2021
60690bf
chore: improve hasSessionKey key check
EclesioMeloJunior Jul 26, 2021
d5a75ac
chore: update params to represent better data
EclesioMeloJunior Jul 26, 2021
10e598b
chore: improve func name to DecodeKeyPairFromHex
EclesioMeloJunior Jul 26, 2021
33e51b0
Merge branch 'development' into eclesio/rpc-has-session-keys
EclesioMeloJunior Jul 26, 2021
812309e
chore: get back func names to avoid naming conflicts
EclesioMeloJunior Jul 27, 2021
d1e5621
Merge branch 'eclesio/rpc-has-session-keys' of github.com:ChainSafe/g…
EclesioMeloJunior Jul 27, 2021
fb91dbd
chore: update go.sum
EclesioMeloJunior Jul 27, 2021
bd65835
Merge branch 'development' into eclesio/subscribe-justification-rpc
EclesioMeloJunior Jul 28, 2021
338f0b8
chore: update grandpa_subscribeJustification return response
EclesioMeloJunior Jul 28, 2021
9c659a5
chore: fix lint issues
EclesioMeloJunior Jul 28, 2021
d666381
chore: check the len of the slice of decoded keys
EclesioMeloJunior Jul 28, 2021
d9943a7
chore: update exports comments
EclesioMeloJunior Jul 28, 2021
74e520e
chore: update the import style
EclesioMeloJunior Jul 28, 2021
16ad5dd
chore: improve DecodeKeyPairFromHex export comment
EclesioMeloJunior Jul 28, 2021
550a091
Merge branch 'development' into eclesio/rpc-has-session-keys
EclesioMeloJunior Jul 29, 2021
d741597
chore: hasSessionKeys test fixed
EclesioMeloJunior Jul 30, 2021
a759f8c
Merge branch 'eclesio/rpc-has-session-keys' of github.com:ChainSafe/g…
EclesioMeloJunior Jul 30, 2021
2734ce7
chore: improve export function comment
EclesioMeloJunior Jul 30, 2021
38bb583
Merge branch 'development' into eclesio/subscribe-justification-rpc
EclesioMeloJunior Jul 30, 2021
0b47095
Merge branch 'eclesio/subscribe-justification-rpc' of github.com:Chai…
EclesioMeloJunior Jul 30, 2021
55dd726
chore: group rpc methods string in a unique place
EclesioMeloJunior Jul 30, 2021
9890ee8
chore: use chan struct{}
EclesioMeloJunior Jul 30, 2021
a33064f
chore: fix tests that uses wsconn
EclesioMeloJunior Jul 31, 2021
716d6b3
chore: fix subscription test
EclesioMeloJunior Jul 31, 2021
2b20c8d
chore: improve log message
EclesioMeloJunior Jul 31, 2021
68ebfc4
chore: fix lint issues
EclesioMeloJunior Aug 1, 2021
204f1d3
chore: increase the author RPC method qty
EclesioMeloJunior Aug 3, 2021
a48b211
chore: fix deepsource style error
EclesioMeloJunior Aug 3, 2021
e4d91ca
chore: keep just related changes
EclesioMeloJunior Aug 3, 2021
d65fb0d
Merge branch 'development' into eclesio/rpc-has-session-keys
EclesioMeloJunior Aug 4, 2021
9adb382
Merge branch 'development' into eclesio/rpc-has-session-keys
EclesioMeloJunior Aug 4, 2021
9e614df
Merge branch 'development' into eclesio/rpc-has-session-keys
EclesioMeloJunior Aug 5, 2021
3d5771a
Merge branch 'development' into eclesio/rpc-has-session-keys
EclesioMeloJunior Aug 6, 2021
a7c3cf6
chore: improve test coverage
EclesioMeloJunior Aug 6, 2021
1517350
Merge branch 'eclesio/rpc-has-session-keys' of github.com:ChainSafe/g…
EclesioMeloJunior Aug 6, 2021
6c96cf9
chore: improve test coverage on lib/keystore/helpers.go
EclesioMeloJunior Aug 6, 2021
fd5e09f
chore: improve testing and remove unused function
EclesioMeloJunior Aug 6, 2021
0cb326f
chore: create more test cases to hasSessionKey RPC method
EclesioMeloJunior Aug 6, 2021
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: 10 additions & 0 deletions dot/core/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -461,6 +461,16 @@ 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
1 change: 1 addition & 0 deletions dot/rpc/modules/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ 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: 72 additions & 11 deletions dot/rpc/modules/author.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,14 @@
package modules

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

"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 @@ -35,8 +36,17 @@ 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 []string
type KeyInsertRequest struct {
Type string
Seed string
PublicKey string
}

// Extrinsic represents a hex-encoded extrinsic
type Extrinsic struct {
Expand Down Expand Up @@ -64,6 +74,18 @@ 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 @@ -94,27 +116,66 @@ func NewAuthorModule(logger log.Logger, coreAPI CoreAPI, txStateAPI TransactionS
}
}

// InsertKey inserts a key into the keystore
func (am *AuthorModule) InsertKey(r *http.Request, req *KeyInsertRequest, res *KeyInsertResponse) error {
keyReq := *req
// 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
}

pkDec, err := common.HexToBytes(keyReq[1])
data, err := am.coreAPI.DecodeSessionKeys(pkeys)
if err != nil {
*res = false
return err
}

privateKey, err := keystore.DecodePrivateKey(pkDec, keystore.DetermineKeyType(keyReq[0]))
var decodedKeys *[]decodedKey
err = scale.Unmarshal(data, &decodedKeys)
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)
if err != nil {
return err
}

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

if !reflect.DeepEqual(keyPair.Public().Hex(), keyReq[2]) {
return fmt.Errorf("generated public key does not equal provide public key")
//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")
}

am.coreAPI.InsertKey(keyPair)
Expand Down
74 changes: 70 additions & 4 deletions dot/rpc/modules/author_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,78 @@ 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 @@ -202,8 +267,8 @@ func TestAuthorModule_InsertKey(t *testing.T) {
args: args{
req: &KeyInsertRequest{
"babe",
"0xb7e9185065667390d2ad952a5324e8c365c9bf503dcf97c67a5ce861afe97309",
"0x6246ddf254e0b4b4e7dffefc8adf69d212b98ac2b579c362b473fec8c40b4c0a",
"0xdad5131003242c37c227f744f82118dd59a24b949ae264a93d949100738c196c",
},
},
},
Expand All @@ -214,9 +279,10 @@ func TestAuthorModule_InsertKey(t *testing.T) {
coreAPI: mockCoreAPI,
},
args: args{
req: &KeyInsertRequest{"gran",
"0xb7e9185065667390d2ad952a5324e8c365c9bf503dcf97c67a5ce861afe97309b7e9185065667390d2ad952a5324e8c365c9bf503dcf97c67a5ce861afe97309",
"0xb7e9185065667390d2ad952a5324e8c365c9bf503dcf97c67a5ce861afe97309",
req: &KeyInsertRequest{
"gran",
"0xb48004c6e1625282313b07d1c9950935e86894a2e4f21fb1ffee9854d180c781",
"0xa7d6507d59f8871b8f1a0f2c32e219adfacff4c9fcb05b0b2d8ebd6a65c88ee6",
},
},
},
Expand Down
37 changes: 23 additions & 14 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 := 7
qtyAuthorMethods := 8

rpcService := NewService()
sysMod := modules.NewSystemModule(nil, nil, nil, nil, nil, nil)
Expand Down
1 change: 0 additions & 1 deletion go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,6 @@ github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfb
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.4 h1:l75CXGRSwbaYNpl/Z2X1XIIAMSCquvXgpVZDhwEIJsc=
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a1/R87v0=
Expand Down
32 changes: 30 additions & 2 deletions lib/crypto/sr25519/sr25519.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,9 +83,13 @@ func NewKeypairFromPrivate(priv *PrivateKey) (*Keypair, error) {
}

// NewKeypairFromSeed returns a new sr25519 Keypair given a seed
func NewKeypairFromSeed(seed []byte) (*Keypair, error) {
func NewKeypairFromSeed(keystr []byte) (*Keypair, error) {
if len(keystr) != SeedLength {
return nil, errors.New("cannot generate key from seed: seed is not 32 bytes long")
}

buf := [SeedLength]byte{}
copy(buf[:], seed)
copy(buf[:], keystr)
msc, err := sr25519.NewMiniSecretKeyFromRaw(buf)
if err != nil {
return nil, err
Expand Down Expand Up @@ -154,6 +158,30 @@ func NewPrivateKey(in []byte) (*PrivateKey, error) {
return priv, err
}

// NewPrivateKeyFromHex returns a private key from a hex-encoded private key
func NewPrivateKeyFromHex(keystr string) (*PrivateKey, error) {
seedBytes, err := common.HexToBytes(keystr)
if err != nil {
return nil, err
}

if len(seedBytes) != PrivateKeyLength {
return nil, errors.New("cannot create public key: input is not 32 bytes")
}

var privKeyBytes [32]byte
copy(privKeyBytes[:], seedBytes)

miniSecretKey, err := sr25519.NewMiniSecretKeyFromRaw(privKeyBytes)
if err != nil {
return nil, err
}

return &PrivateKey{
key: miniSecretKey.ExpandUniform(),
}, nil
}

// GenerateKeypair returns a new sr25519 keypair
func GenerateKeypair() (*Keypair, error) {
priv, pub, err := sr25519.GenerateKeypair()
Expand Down
14 changes: 14 additions & 0 deletions lib/keystore/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,20 @@ func DecodePrivateKey(in []byte, keytype crypto.KeyType) (priv crypto.PrivateKey
return priv, err
}

// DecodeKeyPairFromHex turns an hex-encoded private key into a keypair
func DecodeKeyPairFromHex(keystr []byte, keytype crypto.KeyType) (kp crypto.Keypair, err error) {
switch keytype {
case crypto.Sr25519Type:
kp, err = sr25519.NewKeypairFromSeed(keystr)
case crypto.Ed25519Type:
kp, err = ed25519.NewKeypairFromSeed(keystr)
default:
return nil, errors.New("cannot decode key: invalid key type")
}

return kp, err
}

// GenerateKeypair create a new keypair with the corresponding type and saves
// it to basepath/keystore/[public key].key in json format encrypted using the
// specified password and returns the resulting filepath of the new key
Expand Down
2 changes: 2 additions & 0 deletions lib/runtime/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ var (
BlockBuilderApplyExtrinsic = "BlockBuilder_apply_extrinsic"
// BlockBuilderFinalizeBlock is the runtime API call BlockBuilder_finalize_block
BlockBuilderFinalizeBlock = "BlockBuilder_finalize_block"
// DecodeSessionKeys is the runtime API call SessionKeys_decode_session_keys
DecodeSessionKeys = "SessionKeys_decode_session_keys"
)

// GrandpaAuthoritiesKey is the location of GRANDPA authority data in the storage trie for LEGACY_NODE_RUNTIME and NODE_RUNTIME
Expand Down
Loading