diff --git a/src/gmmpp_msgs.erl b/src/gmmpp_msgs.erl index a8d03ad..5eb0f21 100644 --- a/src/gmmpp_msgs.erl +++ b/src/gmmpp_msgs.erl @@ -9,6 +9,7 @@ -export([ validate/2 + , encode/3 , decode/3 , encode_request/4 , encode_reply/4 @@ -59,6 +60,8 @@ validate(#{ connect := #{ pubkey := PK , versions := Versions , pool_id := PoolId , extra_pubkeys := Extra + , type := Type + , nonces := Nonces }} = Msg, _Vsn) -> valid({list, protocol}, Protocols), valid({list, version} , Versions), @@ -66,6 +69,8 @@ validate(#{ connect := #{ pubkey := PK valid(contract, PoolId), valid(pubkey, PK), valid({list, pubkey}, Extra), + valid(type, Type), + valid(pos_int, Nonces), Msg; validate(#{ connect_ack := #{ protocol := Protocol , version := Version }} = Msg, _Vsn) -> @@ -74,9 +79,11 @@ validate(#{ connect_ack := #{ protocol := Protocol Msg; validate(#{ candidate := #{ seq := Seq , candidate := C + , target := Target , nonces := Nonces , edge_bits := EdgeBits } } = Msg, _Vsn) -> valid(candidate, C), + valid(target, Target), valid(nonces, Nonces), valid(seq, Seq), valid(edge_bits, EdgeBits), @@ -86,6 +93,10 @@ validate(#{ get_nonces := #{ seq := Seq valid(seq, Seq), valid(pos_integer, N), Msg; +validate(#{ nonces := #{seq := Seq, nonces := Ns}} = Msg, _vsn) -> + valid(seq, Seq), + valid(nonces, Ns), + Msg; validate(#{ solution := #{ seq := Seq , nonce := Nonce , evidence := Evidence } } = Msg, _Vsn) -> @@ -93,6 +104,9 @@ validate(#{ solution := #{ seq := Seq valid(nonce, Nonce), valid(evidence, Evidence), Msg; +validate(#{ solution_accepted := #{ seq := Seq }} = Msg, _Vsn) -> + valid(seq, Seq), + Msg; validate(#{ no_solution := #{ seq := Seq , nonce := Nonce } } = Msg, _Vsn) -> valid(seq, Seq), @@ -101,11 +115,13 @@ validate(#{ no_solution := #{ seq := Seq validate(#{ stop_mining := #{} } = Msg, _Vsn) -> Msg. -encode_connect(#{ protocols := _Protocols - , versions := _Versions - , pool_id := _PoolId - , pubkey := _Pubkey - , signature := _Sig } = Params, Id) -> +encode_connect(#{ protocols := _Protocols + , versions := _Versions + , pool_id := _PoolId + , pubkey := _Pubkey + , extra_pubkeys := _Extra + , type := _Type + , signature := _Sig } = Params, Id) -> encode_request(#{connect => Params}, Id, connect_protocol(), connect_version()). decode_connect(MsgBin) -> @@ -145,6 +161,15 @@ decode(MsgBin, ?PROTOCOL_JSON, Vsn) -> end end. +encode(#{call := Req0}, P, V) -> + {Id, Req} = maps:take(id, Req0), + encode_request(Req, Id, P, V); +encode(#{notification := #{msg := Msg}}, P, V) -> + encode_msg(Msg, P, V); +encode(#{reply := Reply0}, P, V) when is_map(Reply0) -> + {Id, Reply} = maps:take(id, Reply0), + encode_reply(Reply, Id, P, V). + encode_msg(Msg0, ?PROTOCOL_JSON, Vsn) -> Msg = validate(Msg0, Vsn), [{Method, Args}] = maps:to_list(Msg), @@ -190,13 +215,15 @@ encode_error(Reason) -> , <<"message">> => Reason }. error_code(mining_disabled ) -> -32000; -error_code(pool_exists ) -> -32001; +error_code(nyi ) -> -32001; %% random.org uses this code for nyi error_code(pool_not_found ) -> -32002; -error_code(unknown_contract ) -> -32003; -error_code(invalid_prefix ) -> -32004; -error_code(invalid_encoding ) -> -32005; -error_code(outdated ) -> -32006; -error_code(solution_mismatch) -> -32007; +error_code(pool_exists ) -> -32003; +error_code(unknown_contract ) -> -32004; +error_code(invalid_prefix ) -> -32005; +error_code(invalid_encoding ) -> -32006; +error_code(outdated ) -> -32007; +error_code(solution_mismatch) -> -32008; +error_code(invalid_input ) -> -32009; error_code(unknown_method ) -> -32601; error_code(_ ) -> -32603. % internal error @@ -206,30 +233,38 @@ decode_result(#{<<"connect_ack">> := #{ <<"protocol">> := P Msg = #{connect_ack => #{ protocol => P , version => V }}, validate(Msg, Vsn); -decode_result(#{<<"nonces">> := Nonces}, _) -> +decode_result(#{<<"nonces">> := #{ <<"seq">> := Seq + , <<"nonces">> := Nonces}}, _) -> + valid(seq, Seq), valid(nonces, Nonces), - #{nonces => Nonces}. + #{nonces => #{seq => Seq, nonces => Nonces}}. %% Mapping types decode_msg_(<<"connect">>, #{ <<"protocols">> := Protos , <<"versions">> := Vsns , <<"pool_id">> := PoolId , <<"pubkey">> := PK - , <<"extra_pubkeys">> := Extra }) -> + , <<"extra_pubkeys">> := Extra + , <<"type">> := Type + , <<"nonces">> := Nonces }) -> #{connect => #{ protocols => Protos , versions => Vsns , pool_id => PoolId , pubkey => PK , extra_pubkeys => Extra + , type => Type + , nonces => Nonces }}; decode_msg_(<<"get_nonces">>, #{ <<"seq">> := Seq , <<"n">> := N }) -> #{get_nonces => #{seq => Seq, n => N}}; decode_msg_(<<"candidate">>, #{ <<"candidate">> := C + , <<"target">> := Target , <<"nonces">> := Nonces , <<"seq">> := Seq , <<"edge_bits">> := EdgeBits }) -> #{candidate => #{ candidate => C + , target => Target , nonces => Nonces , seq => Seq , edge_bits => EdgeBits }}; @@ -239,6 +274,8 @@ decode_msg_(<<"solution">>, #{ <<"seq">> := Seq #{solution => #{ seq => Seq , nonce => Nonce , evidence => Evidence}}; +decode_msg_(<<"solution_accepted">>, #{<<"seq">> := Seq}) -> + #{solution_accepted => #{seq => Seq}}; decode_msg_(<<"no_solution">>, #{ <<"seq">> := Seq , <<"nonce">> := Nonce }) -> #{no_solution => #{ seq => Seq @@ -256,9 +293,11 @@ 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_(target, T) -> pos_integer(T); 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_(type, T) -> lists:member(T, [miner, monitor]); valid_(nonces, Ns) -> case Ns of [N] -> pos_integer(N);