aboutsummaryrefslogtreecommitdiffstats
path: root/rpc/utils.go
diff options
context:
space:
mode:
Diffstat (limited to 'rpc/utils.go')
-rw-r--r--rpc/utils.go70
1 files changed, 38 insertions, 32 deletions
diff --git a/rpc/utils.go b/rpc/utils.go
index fe482e19d..c249e9b4a 100644
--- a/rpc/utils.go
+++ b/rpc/utils.go
@@ -17,18 +17,27 @@
package rpc
import (
- "crypto/rand"
+ "bufio"
+ crand "crypto/rand"
+ "encoding/binary"
"encoding/hex"
- "errors"
- "fmt"
"math/big"
+ "math/rand"
"reflect"
+ "strings"
+ "sync"
+ "time"
"unicode"
"unicode/utf8"
"golang.org/x/net/context"
)
+var (
+ subscriptionIDGenMu sync.Mutex
+ subscriptionIDGen = idGenerator()
+)
+
// Is this an exported - upper case - name?
func isExported(name string) bool {
rune, _ := utf8.DecodeRuneInString(name)
@@ -219,39 +228,36 @@ METHODS:
return callbacks, subscriptions
}
-func newSubscriptionID() (string, error) {
- var subid [16]byte
- n, _ := rand.Read(subid[:])
- if n != 16 {
- return "", errors.New("Unable to generate subscription id")
+// idGenerator helper utility that generates a (pseudo) random sequence of
+// bytes that are used to generate identifiers.
+func idGenerator() *rand.Rand {
+ if seed, err := binary.ReadVarint(bufio.NewReader(crand.Reader)); err == nil {
+ return rand.New(rand.NewSource(seed))
}
- return "0x" + hex.EncodeToString(subid[:]), nil
+ return rand.New(rand.NewSource(int64(time.Now().Nanosecond())))
}
-// SupportedModules returns the collection of API's that the RPC server offers
-// on which the given client connects.
-func SupportedModules(client Client) (map[string]string, error) {
- req := JSONRequest{
- Id: []byte("1"),
- Version: "2.0",
- Method: MetadataApi + "_modules",
- }
- if err := client.Send(req); err != nil {
- return nil, err
+// NewID generates a identifier that can be used as an identifier in the RPC interface.
+// e.g. filter and subscription identifier.
+func NewID() ID {
+ subscriptionIDGenMu.Lock()
+ defer subscriptionIDGenMu.Unlock()
+
+ id := make([]byte, 16)
+ for i := 0; i < len(id); i += 7 {
+ val := subscriptionIDGen.Int63()
+ for j := 0; i+j < len(id) && j < 7; j++ {
+ id[i+j] = byte(val)
+ val >>= 8
+ }
}
- var response JSONSuccessResponse
- if err := client.Recv(&response); err != nil {
- return nil, err
+ rpcId := hex.EncodeToString(id)
+ // rpc ID's are RPC quantities, no leading zero's and 0 is 0x0
+ rpcId = strings.TrimLeft(rpcId, "0")
+ if rpcId == "" {
+ rpcId = "0"
}
- if response.Result != nil {
- mods := make(map[string]string)
- if modules, ok := response.Result.(map[string]interface{}); ok {
- for m, v := range modules {
- mods[m] = fmt.Sprintf("%s", v)
- }
- return mods, nil
- }
- }
- return nil, fmt.Errorf("unable to retrieve modules")
+
+ return ID("0x" + rpcId)
}