diff --git a/src/gmmpp_msgs.erl b/src/gmmpp_msgs.erl index 7680144..a8d03ad 100644 --- a/src/gmmpp_msgs.erl +++ b/src/gmmpp_msgs.erl @@ -57,32 +57,34 @@ protocols(_Vsn) -> [?PROTOCOL]. validate(#{ connect := #{ pubkey := PK , protocols := Protocols , versions := Versions + , pool_id := PoolId + , extra_pubkeys := Extra }} = Msg, _Vsn) -> valid({list, protocol}, Protocols), valid({list, version} , Versions), valid(pubkey, PK), + valid(contract, PoolId), + valid(pubkey, PK), + valid({list, pubkey}, Extra), Msg; -validate(#{ connect_ack := #{ protocol := Protocol0 - , version := Version - , pubkey := PK - , edge_bits := EB }} = Msg, _Vsn) -> - Protocol = binary_to_existing_atom(Protocol0, utf8), +validate(#{ connect_ack := #{ protocol := Protocol + , version := Version }} = Msg, _Vsn) -> valid(protocol, Protocol), valid(version, Version), - valid(pubkey, PK), - valid(edgebits, EB), - Msg#{ protocol => Protocol }; -validate(#{ nonces := #{ seq := Seq - , n := N } } = Msg, _Vsn) -> - valid(seq, Seq), - valid(pos_int, N), Msg; -validate(#{ candidate := #{ candidate := C +validate(#{ candidate := #{ seq := Seq + , candidate := C , nonces := Nonces - , seq := Seq } } = Msg, _Vsn) -> + , edge_bits := EdgeBits } } = Msg, _Vsn) -> valid(candidate, C), valid(nonces, Nonces), valid(seq, Seq), + valid(edge_bits, EdgeBits), + Msg; +validate(#{ get_nonces := #{ seq := Seq + , n := N }} = Msg, _Vsn) -> + valid(seq, Seq), + valid(pos_integer, N), Msg; validate(#{ solution := #{ seq := Seq , nonce := Nonce @@ -91,9 +93,6 @@ validate(#{ solution := #{ seq := Seq valid(nonce, Nonce), valid(evidence, Evidence), Msg; -validate(#{ solution_ack := #{ seq := Seq } } = Msg, _Vsn) -> - valid(seq, Seq), - Msg; validate(#{ no_solution := #{ seq := Seq , nonce := Nonce } } = Msg, _Vsn) -> valid(seq, Seq), @@ -136,7 +135,7 @@ decode(MsgBin, ?PROTOCOL_JSON, Vsn) -> #{ <<"id">> := Id , <<"result">> := Result } -> #{ reply => #{ id => Id - , result => validate(decode_result(Result), Vsn) }}; + , result => decode_result(Result, Vsn) }}; #{ <<"id">> := Id , <<"error">> := #{ <<"code">> := Code , <<"message">> := Message }} -> @@ -151,7 +150,7 @@ encode_msg(Msg0, ?PROTOCOL_JSON, Vsn) -> [{Method, Args}] = maps:to_list(Msg), json_encode(#{ <<"jsonrpc">> => <<"2.0">> , <<"method">> => Method - , <<"args">> => Args }). + , <<"params">> => Args }). encode_request(Req0, Id, ?PROTOCOL_JSON, Vsn) -> Req = validate(Req0, Vsn), @@ -159,7 +158,7 @@ encode_request(Req0, Id, ?PROTOCOL_JSON, Vsn) -> json_encode(#{ <<"jsonrpc">> => <<"2.0">> , <<"id">> => Id , <<"method">> => Method - , <<"args">> => Args }). + , <<"params">> => Args }). encode_reply(Reply0, Id, ?PROTOCOL_JSON, Vsn) when is_map(Reply0) -> Reply = validate(Reply0, Vsn), @@ -170,10 +169,10 @@ encode_reply(Reply0, Id, ?PROTOCOL_JSON, Vsn) when is_map(Reply0) -> encode_reply(Reply, Id, ?PROTOCOL_JSON, _Vsn) -> Msg = case Reply of {error, Reason} -> + Error = encode_error(Reason), #{ <<"jsonrpc">> => <<"2.0">> , <<"id">> => Id - , <<"error">> => #{ <<"code">> => error_code(Reason) - , <<"message">> => Reason }}; + , <<"error">> => Error}; ok -> #{ <<"jsonrpc">> => <<"2.0">> , <<"id">> => Id @@ -184,6 +183,12 @@ encode_reply(Reply, Id, ?PROTOCOL_JSON, _Vsn) -> json_encode(Msg) -> iolist_to_binary(json:encode(Msg)). +encode_error(#{code := _, message := _} = E) -> + E; +encode_error(Reason) -> + #{ <<"code">> => error_code(Reason) + , <<"message">> => Reason }. + error_code(mining_disabled ) -> -32000; error_code(pool_exists ) -> -32001; error_code(pool_not_found ) -> -32002; @@ -195,27 +200,49 @@ error_code(solution_mismatch) -> -32007; error_code(unknown_method ) -> -32601; error_code(_ ) -> -32603. % internal error -decode_result(<<"ok">>) -> ok; -decode_result(#{<<"nonces">> := Nonces}) -> #{nonces => Nonces}. +decode_result(<<"ok">>, _) -> ok; +decode_result(#{<<"connect_ack">> := #{ <<"protocol">> := P + , <<"version">> := V }}, Vsn) -> + Msg = #{connect_ack => #{ protocol => P + , version => V }}, + validate(Msg, Vsn); +decode_result(#{<<"nonces">> := Nonces}, _) -> + valid(nonces, Nonces), + #{nonces => Nonces}. %% Mapping types -decode_msg_(<<"connect">>, #{ <<"pubkey">> := PK }) -> - #{connect => #{pubkey => PK}}; -decode_msg_(<<"nonces">>, #{ <<"seq">> := Seq - , <<"n">> := N }) -> - #{nonces => #{seq => Seq, n => N}}; +decode_msg_(<<"connect">>, #{ <<"protocols">> := Protos + , <<"versions">> := Vsns + , <<"pool_id">> := PoolId + , <<"pubkey">> := PK + , <<"extra_pubkeys">> := Extra }) -> + #{connect => #{ protocols => Protos + , versions => Vsns + , pool_id => PoolId + , pubkey => PK + , extra_pubkeys => Extra + }}; +decode_msg_(<<"get_nonces">>, #{ <<"seq">> := Seq + , <<"n">> := N }) -> + #{get_nonces => #{seq => Seq, n => N}}; decode_msg_(<<"candidate">>, #{ <<"candidate">> := C , <<"nonces">> := Nonces - , <<"seq">> := Seq }) -> + , <<"seq">> := Seq + , <<"edge_bits">> := EdgeBits }) -> #{candidate => #{ candidate => C , nonces => Nonces - , seq => Seq }}; -decode_msg_(<<"solution">>, #{ <<"seq">> := Seq - , <<"nonces">> := Nonces + , seq => Seq + , edge_bits => EdgeBits }}; +decode_msg_(<<"solution">>, #{ <<"seq">> := Seq + , <<"nonce">> := Nonce , <<"evidence">> := Evidence }) -> #{solution => #{ seq => Seq - , nonce => Nonces - , evidence => Evidence}}. + , nonce => Nonce + , evidence => Evidence}}; +decode_msg_(<<"no_solution">>, #{ <<"seq">> := Seq + , <<"nonce">> := Nonce }) -> + #{no_solution => #{ seq => Seq + , nonce => Nonce }}. valid(Type, Val) -> try valid_(Type, Val) @@ -225,12 +252,13 @@ valid(Type, Val) -> end. valid_({list,T}, Ps) -> lists:all(fun(X) -> valid_(T, X) end, Ps); -valid_(protocol, P) -> is_binary(P); -valid_(version, V) -> is_binary(V); -valid_(pubkey, PK) -> ok_tuple(gmser_api_encoder:safe_decode(account_pubkey, PK)); -valid_(seq, Seq) -> pos_integer(Seq); -valid_(edgebits, E) -> pos_integer(E); -valid_(pos_int, I) -> pos_integer(I); +valid_(protocol, P) -> is_binary(P); +valid_(version, V) -> is_binary(V); +valid_(pubkey, PK) -> ok_tuple(gmser_api_encoder:safe_decode(account_pubkey, PK)); +valid_(seq, Seq) -> pos_integer(Seq); +valid_(edge_bits, E) -> pos_integer(E); +valid_(pos_int, I) -> pos_integer(I); +valid_(contract, Id) -> ok_tuple(gmser_api_encoder:safe_defode(contract_pubkey, Id)); valid_(nonces, Ns) -> case Ns of [N] -> pos_integer(N);