rpc, ui/qt/qwhisper, whisper, xeth: introduce complex topic filters

This commit is contained in:
Péter Szilágyi
2015-04-21 18:31:08 +03:00
parent 15586368e5
commit ae4bfc3cfb
11 changed files with 374 additions and 60 deletions

View File

@ -422,12 +422,7 @@ func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) err
case "shh_newIdentity":
*reply = api.xeth().Whisper().NewIdentity()
// case "shh_removeIdentity":
// args := new(WhisperIdentityArgs)
// if err := json.Unmarshal(req.Params, &args); err != nil {
// return err
// }
// *reply = api.xeth().Whisper().RemoveIdentity(args.Identity)
case "shh_hasIdentity":
args := new(WhisperIdentityArgs)
if err := json.Unmarshal(req.Params, &args); err != nil {
@ -439,6 +434,7 @@ func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) err
return NewNotImplementedError(req.Method)
case "shh_newFilter":
// Create a new filter to watch and match messages with
args := new(WhisperFilterArgs)
if err := json.Unmarshal(req.Params, &args); err != nil {
return err

View File

@ -1010,25 +1010,27 @@ func (args *WhisperIdentityArgs) UnmarshalJSON(b []byte) (err error) {
}
type WhisperFilterArgs struct {
To string `json:"to"`
To string
From string
Topics []string
Topics [][]string
}
// UnmarshalJSON implements the json.Unmarshaler interface, invoked to convert a
// JSON message blob into a WhisperFilterArgs structure.
func (args *WhisperFilterArgs) UnmarshalJSON(b []byte) (err error) {
// Unmarshal the JSON message and sanity check
var obj []struct {
To interface{}
Topics []interface{}
To interface{} `json:"to"`
From interface{} `json:"from"`
Topics interface{} `json:"topics"`
}
if err = json.Unmarshal(b, &obj); err != nil {
if err := json.Unmarshal(b, &obj); err != nil {
return NewDecodeParamError(err.Error())
}
if len(obj) < 1 {
return NewInsufficientParamsError(len(obj), 1)
}
// Retrieve the simple data contents of the filter arguments
if obj[0].To == nil {
args.To = ""
} else {
@ -1038,17 +1040,52 @@ func (args *WhisperFilterArgs) UnmarshalJSON(b []byte) (err error) {
}
args.To = argstr
}
t := make([]string, len(obj[0].Topics))
for i, j := range obj[0].Topics {
argstr, ok := j.(string)
if obj[0].From == nil {
args.From = ""
} else {
argstr, ok := obj[0].From.(string)
if !ok {
return NewInvalidTypeError("topics["+string(i)+"]", "is not a string")
return NewInvalidTypeError("from", "is not a string")
}
t[i] = argstr
args.From = argstr
}
args.Topics = t
// Construct the nested topic array
if obj[0].Topics != nil {
// Make sure we have an actual topic array
list, ok := obj[0].Topics.([]interface{})
if !ok {
return NewInvalidTypeError("topics", "is not an array")
}
// Iterate over each topic and handle nil, string or array
topics := make([][]string, len(list))
for idx, field := range list {
switch value := field.(type) {
case nil:
topics[idx] = []string{""}
case string:
topics[idx] = []string{value}
case []interface{}:
topics[idx] = make([]string, len(value))
for i, nested := range value {
switch value := nested.(type) {
case nil:
topics[idx][i] = ""
case string:
topics[idx][i] = value
default:
return NewInvalidTypeError(fmt.Sprintf("topic[%d][%d]", idx, i), "is not a string")
}
}
default:
return NewInvalidTypeError(fmt.Sprintf("topic[%d]", idx), "not a string or array")
}
}
args.Topics = topics
}
return nil
}

View File

@ -1943,7 +1943,7 @@ func TestWhisperFilterArgs(t *testing.T) {
input := `[{"topics": ["0x68656c6c6f20776f726c64"], "to": "0x34ag445g3455b34"}]`
expected := new(WhisperFilterArgs)
expected.To = "0x34ag445g3455b34"
expected.Topics = []string{"0x68656c6c6f20776f726c64"}
expected.Topics = [][]string{[]string{"0x68656c6c6f20776f726c64"}}
args := new(WhisperFilterArgs)
if err := json.Unmarshal([]byte(input), &args); err != nil {