This commit is contained in:
Amaury Chamayou 2020-07-20 14:07:33 +01:00 коммит произвёл GitHub
Родитель b9d442786c
Коммит 2b6e358e62
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
42 изменённых файлов: 319 добавлений и 705 удалений

Просмотреть файл

@ -22,7 +22,7 @@ def wait_for_global_commit(client, seqno, view, timeout=3):
assert (
r.status == http.HTTPStatus.OK
), f"tx request returned HTTP status {r.status}"
status = TxStatus(r.result["status"])
status = TxStatus(r.body["status"])
if status == TxStatus.Committed:
return
elif status == TxStatus.Invalid:
@ -40,24 +40,25 @@ class Checker:
self.notification_queue = notification_queue
self.notified_commit = 0
# TODO: that API's not right!
def __call__(self, rpc_result, result=None, error=None, timeout=2):
if error is not None:
if callable(error):
assert error(
rpc_result.status, rpc_result.error
), f"{rpc_result.status}: {rpc_result.error}"
rpc_result.status, rpc_result.body
), f"{rpc_result.status}: {rpc_result.body}"
else:
assert rpc_result.error == error, "Expected {}, got {}".format(
error, rpc_result.error
assert rpc_result.body == error, "Expected {}, got {}".format(
error, rpc_result.body
)
return
if result is not None:
if callable(result):
assert result(rpc_result.result), rpc_result.result
assert result(rpc_result.body), rpc_result.body
else:
assert rpc_result.result == result, "Expected {}, got {}".format(
result, rpc_result.result
assert rpc_result.body == result, "Expected {}, got {}".format(
result, rpc_result.body
)
assert rpc_result.seqno and rpc_result.view, rpc_result

Просмотреть файл

@ -24,7 +24,7 @@ import websocket
def truncate(string, max_len=256):
if len(string) > max_len:
return string[: max_len - 3] + "..."
return f"{string[: max_len]} + {len(string) - max_len} chars"
else:
return string
@ -40,20 +40,28 @@ DEFAULT_REQUEST_TIMEOUT_SEC = 3
class Request:
def __init__(
self, method, params=None, http_verb="POST", headers=None, params_in_query=None
self, path, params=None, http_verb="POST", headers=None, params_in_query=None
):
if headers is None:
headers = {}
# TODO: remove
if params_in_query is None:
params_in_query = http_verb == "GET"
self.method = method
self.path = path
self.params = params
self.http_verb = http_verb
self.headers = headers
self.params_in_query = params_in_query
def __str__(self):
return (
f"{self.http_verb} {self.path} {self.headers} " + truncate(f"{self.params}")
if self.params is not None
else ""
)
def int_or_none(v):
return int(v) if v is not None else None
@ -68,34 +76,29 @@ class FakeSocket:
class Response:
def __init__(self, status, result, error, seqno, view, global_commit, headers):
def __init__(self, status, body, seqno, view, global_commit, headers):
self.status = status
self.result = result
self.error = error
self.body = body
self.seqno = seqno
self.view = view
self.global_commit = global_commit
self.headers = headers
# TODO: what's this for?
def to_dict(self):
d = {
return {
"seqno": self.seqno,
"global_commit": self.global_commit,
"view": self.view,
"body": self.body,
}
if self.result is not None:
d["result"] = self.result
else:
d["error"] = self.error
return d
def __str__(self):
versioned = (self.view, self.seqno) != (None, None)
body = self.result if f"{self.status}"[0] == "2" else self.error
return (
f"{self.status} "
+ (f"@{self.view}.{self.seqno} " if versioned else "")
+ truncate(f"{body}")
+ truncate(f"{self.body}")
)
@staticmethod
@ -112,8 +115,7 @@ class Response:
return Response(
status=rr.status_code,
result=parsed_body if rr.ok else None,
error=None if rr.ok else parsed_body,
body=parsed_body,
seqno=int_or_none(rr.headers.get(CCF_TX_SEQNO_HEADER)),
view=int_or_none(rr.headers.get(CCF_TX_VIEW_HEADER)),
global_commit=int_or_none(rr.headers.get(CCF_GLOBAL_COMMIT_HEADER)),
@ -126,7 +128,6 @@ class Response:
response = HTTPResponse(sock)
response.begin()
raw_body = response.read(raw)
ok = response.status == 200
content_type = response.headers.get("content-type")
if content_type == "application/json":
@ -140,8 +141,7 @@ class Response:
return Response(
status=response.status,
result=parsed_body if ok else None,
error=None if ok else parsed_body,
body=parsed_body,
seqno=int_or_none(response.getheader(CCF_TX_SEQNO_HEADER)),
view=int_or_none(response.getheader(CCF_TX_VIEW_HEADER)),
global_commit=int_or_none(response.getheader(CCF_GLOBAL_COMMIT_HEADER)),
@ -158,35 +158,6 @@ def human_readable_size(n):
return f"{n:,.2f} {suffixes[i]}"
class RPCLogger:
def log_request(self, request, name, description):
LOG.info(
f"{name} {request.http_verb} {request.method}"
+ (truncate(f" {request.params}") if request.params is not None else "")
+ f"{description}"
)
def log_response(self, response):
LOG.debug(response)
class RPCFileLogger(RPCLogger):
def __init__(self, path):
self.path = path
def log_request(self, request, name, description):
with open(self.path, "a") as f:
f.write(f">> Request: {request.http_verb} {request.method}" + os.linesep)
json.dump(request.params, f, indent=2)
f.write(os.linesep)
def log_response(self, response):
with open(self.path, "a") as f:
f.write("<< Response:" + os.linesep)
json.dump(response.to_dict() if response else "None", f, indent=2)
f.write(os.linesep)
class CCFConnectionException(Exception):
pass
@ -245,7 +216,7 @@ class CurlClient:
else:
cmd = ["curl"]
url = f"https://{self.host}:{self.port}{request.method}"
url = f"https://{self.host}:{self.port}{request.path}"
if request.params_in_query:
if request.params is not None:
@ -269,7 +240,7 @@ class CurlClient:
msg_bytes = request.params
else:
msg_bytes = json.dumps(request.params).encode()
LOG.debug(f"Writing request body: {msg_bytes}")
LOG.debug(f"Writing request body: {truncate(msg_bytes)}")
nf.write(msg_bytes)
nf.flush()
cmd.extend(["--data-binary", f"@{nf.name}"])
@ -367,7 +338,7 @@ class RequestClient:
request_args = {
"method": request.http_verb,
"url": f"https://{self.host}:{self.port}{request.method}",
"url": f"https://{self.host}:{self.port}{request.path}",
"auth": auth_value,
"headers": extra_headers,
}
@ -434,7 +405,7 @@ class WSClient:
except Exception as exc:
raise CCFConnectionException from exc
payload = json.dumps(request.params).encode()
path = (request.method).encode()
path = (request.path).encode()
header = struct.pack("<h", len(path)) + path
# FIN, no RSV, BIN, UNMASKED every time, because it's all we support right now
frame = websocket.ABNF(
@ -447,13 +418,12 @@ class WSClient:
(view,) = struct.unpack("<Q", out[10:18])
(global_commit,) = struct.unpack("<Q", out[18:26])
payload = out[26:]
# TODO: move out the decoding!
if status == 200:
result = json.loads(payload) if payload else None
error = None
body = json.loads(payload) if payload else None
else:
result = None
error = payload.decode()
return Response(status, result, error, seqno, view, global_commit, headers={})
body = payload.decode()
return Response(status, body, seqno, view, global_commit, headers={})
class CCFClient:
@ -466,7 +436,6 @@ class CCFClient:
if "connection_timeout" in kwargs
else DEFAULT_CONNECTION_TIMEOUT_SEC
)
self.rpc_loggers = (RPCLogger(),)
self.name = f"[{host}:{port}]"
if os.getenv("CURL_CLIENT"):
@ -477,31 +446,28 @@ class CCFClient:
self.client_impl = RequestClient(host, port, *args, **kwargs)
def _response(self, response):
for logger in self.rpc_loggers:
logger.log_response(response)
LOG.info(response)
return response
# pylint: disable=method-hidden
def _just_rpc(self, method, *args, **kwargs):
def _direct_call(self, method, *args, **kwargs):
is_signed = "signed" in kwargs and kwargs.pop("signed")
r = Request(method, *args, **kwargs)
description = ""
if self.description:
description = f" ({self.description})" + (" [signed]" if is_signed else "")
for logger in self.rpc_loggers:
logger.log_request(r, self.name, description)
LOG.info(f"{self.name} {r} ({description})")
return self._response(self.client_impl.request(r, is_signed))
def rpc(self, *args, **kwargs):
def call(self, *args, **kwargs):
end_time = time.time() + self.connection_timeout
while True:
try:
response = self._just_rpc(*args, **kwargs)
response = self._direct_call(*args, **kwargs)
# Only the first request gets this timeout logic - future calls
# call _just_rpc directly
self.rpc = self._just_rpc
# call _direct_call directly
self.call = self._direct_call
return response
except (CCFConnectionException, TimeoutError) as e:
# If the initial connection fails (e.g. due to node certificate
@ -514,16 +480,16 @@ class CCFClient:
time.sleep(0.1)
def get(self, *args, **kwargs):
return self.rpc(*args, http_verb="GET", **kwargs)
return self.call(*args, http_verb="GET", **kwargs)
def post(self, *args, **kwargs):
return self.rpc(*args, http_verb="POST", **kwargs)
return self.call(*args, http_verb="POST", **kwargs)
def put(self, *args, **kwargs):
return self.rpc(*args, http_verb="PUT", **kwargs)
return self.call(*args, http_verb="PUT", **kwargs)
def delete(self, *args, **kwargs):
return self.rpc(*args, http_verb="DELETE", **kwargs)
return self.call(*args, http_verb="DELETE", **kwargs)
@contextlib.contextmanager
@ -534,7 +500,6 @@ def client(
key=None,
ca=None,
description=None,
log_file=None,
binary_dir=".",
connection_timeout=DEFAULT_CONNECTION_TIMEOUT_SEC,
request_timeout=DEFAULT_REQUEST_TIMEOUT_SEC,
@ -553,7 +518,4 @@ def client(
ws=ws,
)
if log_file is not None:
c.rpc_loggers += (RPCFileLogger(log_file),)
yield c

Просмотреть файл

@ -5,7 +5,7 @@
#include "consensus/pbft/pbft_requests.h"
#include "node/encryptor.h"
#include "node/history.h"
#include "node/rpc/json_rpc.h"
#include "node/rpc/serdes.h"
#include "tests/flatbuffer_wrapper_test.h"
#include <nlohmann/json.hpp>
@ -38,7 +38,7 @@ static std::vector<uint8_t> packed_json_tx()
nlohmann::json j;
j["name"] = std::to_string(account_name);
j["value"] = transaction_value;
return jsonrpc::pack(j, jsonrpc::Pack::MsgPack);
return serdes::pack(j, serdes::Pack::MsgPack);
}
static std::unique_ptr<flatbuffers::DetachedBuffer> fb_tx_buffer()
@ -117,7 +117,7 @@ static void json_msgpack_des(picobench::state& s)
s.start_timer();
for (int i = 0; i < s.iterations(); i++)
{
auto params = jsonrpc::unpack(p, jsonrpc::Pack::MsgPack);
auto params = serdes::unpack(p, serdes::Pack::MsgPack);
std::string name = params["name"];
int64_t value = params["value"];
}
@ -168,7 +168,7 @@ static void jm_large_payload(picobench::state& s)
auto payload = large_payload(S);
nlohmann::json j;
j["data"] = payload;
auto d = jsonrpc::pack(j, jsonrpc::Pack::MsgPack);
auto d = serdes::pack(j, serdes::Pack::MsgPack);
auto data = kv_serialized_data(d);
run_mt_benchmark(s, data);
}

Просмотреть файл

@ -101,7 +101,7 @@ def run(args):
check = ccf.checker.Checker()
check(
c.rpc(
c.post(
"REG_register",
{
"regulator_id": regulator.ccf_id,
@ -113,7 +113,7 @@ def run(args):
result=regulator.ccf_id,
)
check(
c.rpc("REG_get", {"id": regulator.ccf_id}),
c.post("REG_get", {"id": regulator.ccf_id}),
result=[
regulator.country,
scripts[regulator.name],
@ -128,12 +128,12 @@ def run(args):
check = ccf.checker.Checker()
check(
c.rpc(
c.post(
"BK_register", {"bank_id": bank.ccf_id, "country": bank.country}
),
result=bank.ccf_id,
)
check(c.rpc("BK_get", {"id": bank.ccf_id}), result=bank.country)
check(c.post("BK_get", {"id": bank.ccf_id}), result=bank.country)
LOG.debug(f"User {bank} successfully registered as bank")
LOG.success(
@ -145,7 +145,7 @@ def run(args):
with primary.user_client(format="msgpack", user_id=regulators[0].name) as reg_c:
with primary.user_client(
format="msgpack", user_id=banks[0].name, log_file=None
format="msgpack", user_id=banks[0].name
) as c:
with open(args.datafile, newline="") as f:
start_time = perf_counter()
@ -163,7 +163,7 @@ def run(args):
"dst_country": row["dst_country"],
}
check(c.rpc("TX_record", json_tx), result=tx_id)
check(c.post("TX_record", json_tx), result=tx_id)
print(json.dumps(json_tx))
tx_id += 1

Просмотреть файл

@ -44,16 +44,16 @@ def run(args):
) as c:
while True:
time.sleep(1)
resp = reg_c.rpc("REG_poll_flagged").to_dict()
resp = reg_c.post("REG_poll_flagged").to_dict()
if "result" in resp:
flagged_txs = resp["result"]
for flagged in flagged_txs:
# bank reveal the transaction
c.rpc("TX_reveal", {"tx_id": flagged[0]})
c.post("TX_reveal", {"tx_id": flagged[0]})
# regulator get the transaction
tx_resp = reg_c.rpc(
tx_resp = reg_c.post(
"REG_get_revealed", {"tx_id": flagged[0]}
).to_dict()
if "result" in tx_resp:

Просмотреть файл

@ -25,7 +25,7 @@ class AppUser:
network.consortium.add_users(primary, [self.name])
with primary.client(f"user{self.name}") as client:
self.ccf_id = client.get("/app/user_id").result["caller_id"]
self.ccf_id = client.get("/app/user_id").body["caller_id"]
def __str__(self):
return f"{self.ccf_id} ({self.name})"
@ -91,18 +91,18 @@ def run(args):
# Check permissions are enforced
with primary.client(f"user{regulator.name}") as c:
check(
c.rpc("/app/REG_register"), error=check_status(http.HTTPStatus.FORBIDDEN),
c.post("/app/REG_register"), error=check_status(http.HTTPStatus.FORBIDDEN),
)
check(
c.rpc("/app/BK_register"), error=check_status(http.HTTPStatus.FORBIDDEN),
c.post("/app/BK_register"), error=check_status(http.HTTPStatus.FORBIDDEN),
)
with primary.client(f"user{banks[0].name}") as c:
check(
c.rpc("/app/REG_register"), error=check_status(http.HTTPStatus.FORBIDDEN),
c.post("/app/REG_register"), error=check_status(http.HTTPStatus.FORBIDDEN),
)
check(
c.rpc("/app/BK_register"), error=check_status(http.HTTPStatus.FORBIDDEN),
c.post("/app/BK_register"), error=check_status(http.HTTPStatus.FORBIDDEN),
)
# As permissioned manager, register regulator and banks
@ -111,7 +111,7 @@ def run(args):
with primary.client(f"user{manager.name}") as c:
check(
c.rpc(
c.post(
"/app/REG_register",
{
"regulator_id": regulator.ccf_id,
@ -122,12 +122,12 @@ def run(args):
result=regulator.ccf_id,
)
check(
c.rpc("/app/REG_get", {"id": regulator.ccf_id}),
c.post("/app/REG_get", {"id": regulator.ccf_id}),
result=[regulator.country, script],
)
check(
c.rpc(
c.post(
"/app/BK_register",
{"bank_id": regulator.ccf_id, "country": regulator.country},
),
@ -137,16 +137,16 @@ def run(args):
for bank in banks:
check(
c.rpc(
c.post(
"/app/BK_register",
{"bank_id": bank.ccf_id, "country": bank.country},
),
result=bank.ccf_id,
)
check(c.rpc("/app/BK_get", {"id": bank.ccf_id}), result=bank.country)
check(c.post("/app/BK_get", {"id": bank.ccf_id}), result=bank.country)
check(
c.rpc(
c.post(
"/app/REG_register",
{"regulator_id": bank.ccf_id, "country": bank.country},
),
@ -171,9 +171,9 @@ def run(args):
print(transaction)
amount = transaction["amt"]
check(c.rpc("/app/TX_record", transaction), result=tx_id)
check(c.post("/app/TX_record", transaction), result=tx_id)
check(
c.rpc("/app/TX_get", {"tx_id": tx_id}),
c.post("/app/TX_get", {"tx_id": tx_id}),
result={
"amt": amount,
"bank_id": bank.ccf_id,
@ -187,7 +187,7 @@ def run(args):
)
if float(amount) > flagged_amt:
check(
c.rpc("/app/FLAGGED_TX_get", {"tx_id": tx_id}),
c.post("/app/FLAGGED_TX_get", {"tx_id": tx_id}),
result=[regulator.ccf_id, False, transaction["timestamp"]],
)
flagged_tx = {
@ -205,7 +205,7 @@ def run(args):
flagged_txs[tx_id] = flagged_tx
else:
check(
c.rpc("/app/FLAGGED_TX_get", {"tx_id": tx_id}),
c.post("/app/FLAGGED_TX_get", {"tx_id": tx_id}),
error=check_status(http.HTTPStatus.BAD_REQUEST),
)
non_flagged_ids.append(tx_id)
@ -217,20 +217,20 @@ def run(args):
with primary.client(f"user{bank.name}") as c:
# try to poll flagged but fail as you are not a regulator
check(
c.rpc("/app/REG_poll_flagged"),
c.post("/app/REG_poll_flagged"),
error=check_status(http.HTTPStatus.FORBIDDEN),
)
# bank reveal some transactions that were flagged
for i, tx_id in enumerate(flagged_ids):
if i % 2 == 0:
check(c.rpc("/app/TX_reveal", {"tx_id": tx_id}), result=True)
check(c.post("/app/TX_reveal", {"tx_id": tx_id}), result=True)
revealed_tx_ids.append(tx_id)
# bank try to reveal non flagged txs
for tx_id in non_flagged_ids:
check(
c.rpc("/app/TX_reveal", {"tx_id": tx_id}),
c.post("/app/TX_reveal", {"tx_id": tx_id}),
error=check_status(http.HTTPStatus.BAD_REQUEST),
)
@ -238,9 +238,9 @@ def run(args):
with primary.client() as mc:
with primary.client(f"user{regulator.name}") as c:
# assert that the flagged txs that we poll for are correct
resp = c.rpc("/app/REG_poll_flagged")
resp = c.post("/app/REG_poll_flagged")
poll_flagged_ids = []
for poll_flagged in resp.result:
for poll_flagged in resp.body:
# poll flagged is a list [tx_id, regulator_id]
poll_flagged_ids.append(poll_flagged[0])
poll_flagged_ids.sort()
@ -250,14 +250,14 @@ def run(args):
# get from flagged txs, try to get the flagged one that was not revealed
if tx_id not in revealed_tx_ids:
check(
c.rpc("/app/REG_get_revealed", {"tx_id": tx_id}),
c.post("/app/REG_get_revealed", {"tx_id": tx_id}),
error=check_status(http.HTTPStatus.BAD_REQUEST),
)
# get from flagged txs, try to get the flagged ones that were revealed
for tx_id in revealed_tx_ids:
check(
c.rpc("/app/REG_get_revealed", {"tx_id": tx_id}),
c.post("/app/REG_get_revealed", {"tx_id": tx_id}),
result=flagged_txs[tx_id],
)

Просмотреть файл

@ -272,7 +272,7 @@ namespace ccfapp
args.rpc_ctx->set_response_status(HTTP_STATUS_OK);
args.rpc_ctx->set_response_body(
jsonrpc::pack(response, jsonrpc::Pack::Text));
serdes::pack(response, serdes::Pack::Text));
args.rpc_ctx->set_response_header(
http::headers::CONTENT_TYPE, http::headervalues::contenttype::JSON);
return;

Просмотреть файл

@ -394,7 +394,7 @@ namespace loggingapp
{
nlohmann::json notify_j;
notify_j["commit"] = version;
notifier.notify(jsonrpc::pack(notify_j, jsonrpc::Pack::Text));
notifier.notify(serdes::pack(notify_j, serdes::Pack::Text));
}
});
}

Просмотреть файл

@ -9,7 +9,7 @@
#include "lua_interp/lua_interp.h"
#include "node/genesis_gen.h"
#include "node/rpc/json_handler.h"
#include "node/rpc/json_rpc.h"
#include "node/rpc/serdes.h"
#include "node/rpc/test/node_stub.h"
#include "runtime_config/default_whitelists.h"
#include "tls/key_pair.h"
@ -23,12 +23,12 @@
using namespace ccfapp;
using namespace ccf;
using namespace std;
using namespace jsonrpc;
using namespace serdes;
using namespace nlohmann;
auto kp = tls::make_key_pair();
constexpr auto default_format = jsonrpc::Pack::MsgPack;
constexpr auto default_format = serdes::Pack::MsgPack;
constexpr auto content_type =
ccf::jsonhandler::pack_to_content_type(default_format);
@ -56,7 +56,7 @@ TResponse check_error(const vector<uint8_t>& v, http_status expected)
template <typename T>
T parse_response_body(const TResponse& r)
{
const auto body_j = jsonrpc::unpack(r.body, default_format);
const auto body_j = serdes::unpack(r.body, default_format);
return body_j.get<T>();
}
@ -171,7 +171,7 @@ std::vector<uint8_t> make_pc(const string& method, const Params& params)
{
auto request = http::Request(method);
request.set_header(http::headers::CONTENT_TYPE, content_type);
const auto body = jsonrpc::pack(params, default_format);
const auto body = serdes::pack(params, default_format);
request.set_body(&body);
return request.build_request();
}

Просмотреть файл

@ -7,7 +7,7 @@
#include "http/http_parser.h"
#include "http/ws_builder.h"
#include "http/ws_parser.h"
#include "node/rpc/json_rpc.h"
#include "node/rpc/serdes.h"
#include "tls_client.h"
#define FMT_HEADER_ONLY
@ -163,7 +163,7 @@ public:
std::vector<uint8_t> body;
if (!params.is_null())
{
body = jsonrpc::pack(params, jsonrpc::Pack::MsgPack);
body = serdes::pack(params, serdes::Pack::MsgPack);
}
return gen_request(
method,
@ -222,7 +222,7 @@ public:
else if (http::status_success(resp.status))
{
const auto& content_type = resp.headers.find(http::headers::CONTENT_TYPE);
return jsonrpc::unpack(resp.body, jsonrpc::Pack::MsgPack);
return serdes::unpack(resp.body, serdes::Pack::MsgPack);
}
else
{

Просмотреть файл

@ -273,11 +273,11 @@ namespace ccf
tx, caller, id, method, params = ...
function jsucc(id, result)
return {jsonrpc = "2.0", id = id, result = result}
return {serdes = "2.0", id = id, result = result}
end
function jerr(id, code, message)
return {jsonrpc = "2.0", id = id, error = {code = code, message = message}}
return {serdes = "2.0", id = id, error = {code = code, message = message}}
end
handlers = {}

Просмотреть файл

@ -14,7 +14,7 @@
#include "genesis_gen.h"
#include "history.h"
#include "network_state.h"
#include "node/rpc/json_rpc.h"
#include "node/rpc/serdes.h"
#include "node_to_node.h"
#include "notifier.h"
#include "rpc/frontend.h"
@ -382,7 +382,7 @@ namespace ccf
return false;
}
auto j = jsonrpc::unpack(data, jsonrpc::Pack::Text);
auto j = serdes::unpack(data, serdes::Pack::Text);
JoinNetworkNodeToNode::Out resp;
try
@ -471,7 +471,7 @@ namespace ccf
args.config.joining.target_host,
args.config.joining.target_port);
const auto body = jsonrpc::pack(join_params, jsonrpc::Pack::Text);
const auto body = serdes::pack(join_params, serdes::Pack::Text);
http::Request r(fmt::format(
"/{}/{}", ccf::get_actor_prefix(ccf::ActorsType::nodes), "join"));
@ -1171,7 +1171,7 @@ namespace ccf
create_params.consensus_type = network.consensus_type;
create_params.recovery_threshold = args.config.genesis.recovery_threshold;
const auto body = jsonrpc::pack(create_params, jsonrpc::Pack::Text);
const auto body = serdes::pack(create_params, serdes::Pack::Text);
http::Request request(fmt::format(
"/{}/{}", ccf::get_actor_prefix(ccf::ActorsType::members), "create"));
@ -1218,7 +1218,7 @@ namespace ccf
return false;
}
const auto body = jsonrpc::unpack(r.body, jsonrpc::Pack::Text);
const auto body = serdes::unpack(r.body, serdes::Pack::Text);
if (!body.is_boolean())
{
LOG_FAIL_FMT("Expected boolean body in create response");

Просмотреть файл

@ -5,7 +5,7 @@
#include "enclave/rpc_context.h"
#include "endpoint_registry.h"
#include "http/http_consts.h"
#include "node/rpc/json_rpc.h"
#include "node/rpc/serdes.h"
#include <http-parser/http_parser.h>
@ -19,7 +19,7 @@ namespace ccf
* Rather than:
* auto foo = [](auto& args) {
* nlohmann::json params;
* jsonrpc::Pack pack_type;
* serdes::Pack pack_type;
* if (<content-type is JSON>)
* {
* params = unpack(args.rpc_ctx->get_request_body());
@ -72,15 +72,15 @@ namespace ccf
using JsonAdapterResponse = std::variant<ErrorDetails, nlohmann::json>;
static constexpr char const* pack_to_content_type(jsonrpc::Pack p)
static constexpr char const* pack_to_content_type(serdes::Pack p)
{
switch (p)
{
case jsonrpc::Pack::Text:
case serdes::Pack::Text:
{
return http::headervalues::contenttype::JSON;
}
case jsonrpc::Pack::MsgPack:
case serdes::Pack::MsgPack:
{
return http::headervalues::contenttype::MSGPACK;
}
@ -91,10 +91,10 @@ namespace ccf
}
}
static jsonrpc::Pack detect_json_pack(
static serdes::Pack detect_json_pack(
const std::shared_ptr<enclave::RpcContext>& ctx)
{
std::optional<jsonrpc::Pack> packing = std::nullopt;
std::optional<serdes::Pack> packing = std::nullopt;
const auto content_type_it =
ctx->get_request_header(http::headers::CONTENT_TYPE);
@ -103,11 +103,11 @@ namespace ccf
const auto& content_type = content_type_it.value();
if (content_type == http::headervalues::contenttype::JSON)
{
packing = jsonrpc::Pack::Text;
packing = serdes::Pack::Text;
}
else if (content_type == http::headervalues::contenttype::MSGPACK)
{
packing = jsonrpc::Pack::MsgPack;
packing = serdes::Pack::MsgPack;
}
else
{
@ -121,16 +121,16 @@ namespace ccf
}
else
{
packing = jsonrpc::detect_pack(ctx->get_request_body());
packing = serdes::detect_pack(ctx->get_request_body());
}
return packing.value_or(jsonrpc::Pack::Text);
return packing.value_or(serdes::Pack::Text);
}
static nlohmann::json get_params_from_body(
const std::shared_ptr<enclave::RpcContext>& ctx, jsonrpc::Pack pack)
const std::shared_ptr<enclave::RpcContext>& ctx, serdes::Pack pack)
{
return jsonrpc::unpack(ctx->get_request_body(), pack);
return serdes::unpack(ctx->get_request_body(), pack);
}
static nlohmann::json get_params_from_query(
@ -176,7 +176,7 @@ namespace ccf
return params;
}
static std::pair<jsonrpc::Pack, nlohmann::json> get_json_params(
static std::pair<serdes::Pack, nlohmann::json> get_json_params(
const std::shared_ptr<enclave::RpcContext>& ctx)
{
const auto pack = detect_json_pack(ctx);
@ -200,7 +200,7 @@ namespace ccf
static void set_response(
JsonAdapterResponse&& res,
std::shared_ptr<enclave::RpcContext>& ctx,
jsonrpc::Pack packing)
serdes::Pack packing)
{
auto error = std::get_if<ErrorDetails>(&res);
if (error != nullptr)
@ -214,20 +214,20 @@ namespace ccf
ctx->set_response_status(HTTP_STATUS_OK);
switch (packing)
{
case jsonrpc::Pack::Text:
case serdes::Pack::Text:
{
const auto s = fmt::format("{}\n", body->dump());
ctx->set_response_body(std::vector<uint8_t>(s.begin(), s.end()));
break;
}
case jsonrpc::Pack::MsgPack:
case serdes::Pack::MsgPack:
{
ctx->set_response_body(nlohmann::json::to_msgpack(*body));
break;
}
default:
{
throw std::logic_error("Unhandled jsonrpc::Pack");
throw std::logic_error("Unhandled serdes::Pack");
}
}
ctx->set_response_header(

Просмотреть файл

@ -1,362 +0,0 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the Apache 2.0 License.
#pragma once
#include "ds/json.h"
#include <string>
#include <vector>
namespace jsonrpc
{
using SeqNo = uint64_t;
static constexpr auto RPC_VERSION = "2.0";
static constexpr auto ID = "id";
static constexpr auto JSON_RPC = "jsonrpc";
static constexpr auto METHOD = "method";
static constexpr auto READONLY = "readonly";
static constexpr auto PARAMS = "params";
static constexpr auto RESULT = "result";
static constexpr auto ERR = "error";
static constexpr auto CODE = "code";
static constexpr auto MESSAGE = "message";
static constexpr auto DATA = "data";
static constexpr auto SIG = "sig";
static constexpr auto REQ = "req";
// -32000 to -32099 are reserved for implementation-defined server-errors
#define XX_STANDARD_ERROR_CODES \
XX(PARSE_ERROR, -32700) \
XX(INVALID_REQUEST, -32600) \
XX(METHOD_NOT_FOUND, -32601) \
XX(INVALID_PARAMS, -32602) \
XX(INTERNAL_ERROR, -32603) \
XX(SERVER_ERROR_START, -32000) \
XX(SERVER_ERROR_END, -32099)
#define XX_CCF_ERROR_CODES \
XX(TX_NOT_PRIMARY, -32001) \
XX(TX_FAILED_TO_REPLICATE, -32002) \
XX(SCRIPT_ERROR, -32003) \
XX(INSUFFICIENT_RIGHTS, -32004) \
XX(TX_PRIMARY_UNKNOWN, -32005) \
XX(RPC_NOT_SIGNED, -32006) \
XX(INVALID_CLIENT_SIGNATURE, -32007) \
XX(INVALID_CALLER_ID, -32008) \
XX(CODE_ID_NOT_FOUND, -32009) \
XX(CODE_ID_RETIRED, -32010) \
XX(RPC_NOT_FORWARDED, -32011) \
XX(QUOTE_NOT_VERIFIED, -32012) \
XX(APP_ERROR_START, -32050)
using ErrorBaseType = int;
enum StandardErrorCodes : ErrorBaseType
{
#define XX(Name, Value) Name = Value,
XX_STANDARD_ERROR_CODES
#undef XX
};
enum CCFErrorCodes : ErrorBaseType
{
#define XX(Name, Value) Name = Value,
XX_CCF_ERROR_CODES
#undef XX
};
inline std::string get_error_prefix(ErrorBaseType ec)
{
#define XX(Name, Value) \
case (CCFErrorCodes::Name): \
return "[" #Name "]: ";
switch (CCFErrorCodes(ec))
{
XX_CCF_ERROR_CODES
}
#undef XX
#define XX(Name, Value) \
case (StandardErrorCodes::Name): \
return "[" #Name "]: ";
switch (StandardErrorCodes(ec))
{
XX_STANDARD_ERROR_CODES
}
#undef XX
return "";
}
enum class Pack
{
Text,
MsgPack
};
inline std::vector<uint8_t> pack(const nlohmann::json& j, Pack pack)
{
switch (pack)
{
case Pack::Text:
{
auto s = j.dump();
return std::vector<uint8_t>{s.begin(), s.end()};
}
case Pack::MsgPack:
return nlohmann::json::to_msgpack(j);
}
throw std::logic_error("Invalid jsonrpc::Pack");
}
inline nlohmann::json unpack(const std::vector<uint8_t>& data, Pack pack)
{
switch (pack)
{
case Pack::Text:
return nlohmann::json::parse(data);
case Pack::MsgPack:
return nlohmann::json::from_msgpack(data);
}
throw std::logic_error("Invalid jsonrpc::Pack");
}
inline std::optional<jsonrpc::Pack> detect_pack(
const std::vector<uint8_t>& input)
{
if (input.size() == 0)
{
return {};
}
if (input[0] == '{')
{
return jsonrpc::Pack::Text;
}
else
{
return jsonrpc::Pack::MsgPack;
}
}
//
// Requests
//
struct ProcedureCallBase
{
std::string method;
SeqNo id;
};
inline void to_json(nlohmann::json& j, const ProcedureCallBase& pc)
{
j[JSON_RPC] = RPC_VERSION;
j[ID] = pc.id;
j[METHOD] = pc.method;
}
inline void from_json(const nlohmann::json& j, ProcedureCallBase& pc)
{
std::string jsonRpc = j[JSON_RPC];
if (jsonRpc != RPC_VERSION)
throw std::logic_error("Wrong JSON-RPC version: " + j.dump());
pc.id = j[ID];
assign_j(pc.method, j[METHOD]);
}
template <typename T>
struct ProcedureCall : public ProcedureCallBase
{
T params = {};
};
template <typename T>
void to_json(nlohmann::json& j, const ProcedureCall<T>& pc)
{
to_json(j, dynamic_cast<const ProcedureCallBase&>(pc));
j[PARAMS] = pc.params;
}
template <typename T>
void from_json(const nlohmann::json& j, ProcedureCall<T>& pc)
{
from_json(j, dynamic_cast<ProcedureCallBase&>(pc));
pc.params = j[PARAMS];
}
template <>
struct ProcedureCall<void> : public ProcedureCallBase
{};
template <>
inline void to_json(nlohmann::json& j, const ProcedureCall<void>& pc)
{
to_json(j, dynamic_cast<const ProcedureCallBase&>(pc));
j[PARAMS] = nlohmann::json::object();
}
template <>
inline void from_json(const nlohmann::json& j, ProcedureCall<void>& pc)
{
from_json(j, dynamic_cast<ProcedureCallBase&>(pc));
}
//
// Responses
//
template <typename T>
struct Response
{
T result;
SeqNo id;
T* operator->()
{
return &result;
}
};
template <typename T>
void to_json(nlohmann::json& j, const Response<T>& r)
{
j[JSON_RPC] = RPC_VERSION;
j[ID] = r.id;
j[RESULT] = r.result;
}
template <typename T>
void from_json(const nlohmann::json& j, Response<T>& r)
{
std::string jsonRpc = j[JSON_RPC];
if (jsonRpc != RPC_VERSION)
throw std::logic_error("Wrong JSON-RPC version: " + j.dump());
r.id = j[ID];
auto search = j.find(RESULT);
if (search == j.end())
throw std::logic_error("No result field: " + j.dump());
decltype(r.result) temp = *search;
r.result = temp;
}
struct Error
{
ErrorBaseType code;
std::string message;
template <typename ErrorEnum>
Error(ErrorEnum error_code, const std::string& msg = "") :
code(static_cast<ErrorBaseType>(error_code)),
message(get_error_prefix(code) + msg)
{}
};
DECLARE_JSON_TYPE(Error)
DECLARE_JSON_REQUIRED_FIELDS(Error, code, message)
template <typename T>
struct ErrorEx : public Error
{
T data;
};
template <typename T>
void to_json(nlohmann::json& j, const ErrorEx<T>& e)
{
j[CODE] = e.code;
j[MESSAGE] = e.message;
j[DATA] = e.data;
}
template <typename T>
void from_json(const nlohmann::json& j, ErrorEx<T>& e)
{
e.code = j[CODE];
e.message = j[MESSAGE];
e.data = j[DATA];
}
template <typename ErrorEnum>
inline std::pair<bool, nlohmann::json> error(
ErrorEnum error_code, const std::string msg = "")
{
return std::make_pair(false, Error(error_code, msg));
}
template <typename T>
std::pair<bool, nlohmann::json> success(T&& result)
{
nlohmann::json j(result);
return std::make_pair(true, j);
}
inline nlohmann::json result_response(SeqNo id, const nlohmann::json& result)
{
nlohmann::json j;
j[JSON_RPC] = RPC_VERSION;
j[ID] = id;
j[RESULT] = result;
return j;
}
inline nlohmann::json error_response(SeqNo id, const nlohmann::json& error)
{
nlohmann::json j;
j[JSON_RPC] = RPC_VERSION;
j[ID] = id;
j[ERR] = error;
return j;
}
template <typename ErrorEnum>
inline nlohmann::json error_response(
SeqNo id, ErrorEnum error_code, const std::string& msg)
{
nlohmann::json j;
j[JSON_RPC] = RPC_VERSION;
j[ID] = id;
j[ERR] = Error(error_code, msg);
return j;
}
inline std::pair<bool, nlohmann::json> unpack_rpc(
const std::vector<uint8_t>& input, std::optional<Pack>& o_pack)
{
const auto pack = detect_pack(input);
if (!pack.has_value())
{
return jsonrpc::error(
StandardErrorCodes::INVALID_REQUEST,
"Unable to detect packing format of request");
}
o_pack = pack;
nlohmann::json rpc;
try
{
rpc = unpack(input, pack.value());
if (!rpc.is_object())
{
return jsonrpc::error(
StandardErrorCodes::INVALID_REQUEST,
fmt::format("RPC payload is a not a valid object: {}", rpc.dump()));
}
}
catch (const std::exception& e)
{
return error(
StandardErrorCodes::INVALID_REQUEST,
fmt::format("Exception during unpack: {}", e.what()));
}
return {true, rpc};
}
}

66
src/node/rpc/serdes.h Normal file
Просмотреть файл

@ -0,0 +1,66 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the Apache 2.0 License.
#pragma once
#include "ds/json.h"
#include <string>
#include <vector>
namespace serdes
{
enum class Pack
{
Text,
MsgPack
};
inline std::vector<uint8_t> pack(const nlohmann::json& j, Pack pack)
{
switch (pack)
{
case Pack::Text:
{
auto s = j.dump();
return std::vector<uint8_t>{s.begin(), s.end()};
}
case Pack::MsgPack:
return nlohmann::json::to_msgpack(j);
}
throw std::logic_error("Invalid serdes::Pack");
}
inline nlohmann::json unpack(const std::vector<uint8_t>& data, Pack pack)
{
switch (pack)
{
case Pack::Text:
return nlohmann::json::parse(data);
case Pack::MsgPack:
return nlohmann::json::from_msgpack(data);
}
throw std::logic_error("Invalid serdes::Pack");
}
inline std::optional<serdes::Pack> detect_pack(
const std::vector<uint8_t>& input)
{
if (input.size() == 0)
{
return {};
}
if (input[0] == '{')
{
return serdes::Pack::Text;
}
else
{
return serdes::Pack::MsgPack;
}
}
}

Просмотреть файл

@ -13,9 +13,9 @@
#include "node/history.h"
#include "node/network_state.h"
#include "node/rpc/json_handler.h"
#include "node/rpc/json_rpc.h"
#include "node/rpc/member_frontend.h"
#include "node/rpc/node_frontend.h"
#include "node/rpc/serdes.h"
#include "node/rpc/user_frontend.h"
#include "node/test/channel_stub.h"
#include "node_stub.h"
@ -33,7 +33,7 @@ using namespace ccfapp;
using namespace ccf;
using namespace std;
static constexpr auto default_pack = jsonrpc::Pack::MsgPack;
static constexpr auto default_pack = serdes::Pack::MsgPack;
class TestUserFrontend : public SimpleUserRpcFrontend
{
@ -157,7 +157,7 @@ public:
auto maybe_commit = [this](EndpointContext& args) {
const auto parsed =
jsonrpc::unpack(args.rpc_ctx->get_request_body(), default_pack);
serdes::unpack(args.rpc_ctx->get_request_body(), default_pack);
const auto new_value = parsed["value"].get<size_t>();
auto view = args.tx.get_view(values);
@ -363,7 +363,7 @@ StubNodeState stub_node(share_manager);
auto create_simple_request(
const std::string& method = "empty_function",
jsonrpc::Pack pack = default_pack)
serdes::Pack pack = default_pack)
{
http::Request request(method);
request.set_header(
@ -402,9 +402,9 @@ http::SimpleResponseProcessor::Response parse_response(const vector<uint8_t>& v)
}
nlohmann::json parse_response_body(
const vector<uint8_t>& body, jsonrpc::Pack pack = default_pack)
const vector<uint8_t>& body, serdes::Pack pack = default_pack)
{
return jsonrpc::unpack(body, pack);
return serdes::unpack(body, pack);
}
std::optional<SignedReq> get_signed_req(CallerId caller_id)
@ -515,7 +515,7 @@ TEST_CASE("process_pbft")
auto simple_call = create_simple_request();
const nlohmann::json call_body = {{"foo", "bar"}, {"baz", 42}};
const auto serialized_body = jsonrpc::pack(call_body, default_pack);
const auto serialized_body = serdes::pack(call_body, default_pack);
simple_call.set_body(&serialized_body);
const auto serialized_call = simple_call.build_request();
@ -813,14 +813,14 @@ TEST_CASE("MinimalEndpointFunction")
{
prepare_callers();
TestMinimalEndpointFunction frontend(*network.tables);
for (const auto pack_type : {jsonrpc::Pack::Text, jsonrpc::Pack::MsgPack})
for (const auto pack_type : {serdes::Pack::Text, serdes::Pack::MsgPack})
{
{
INFO("Calling echo, with params in body");
auto echo_call = create_simple_request("echo", pack_type);
const nlohmann::json j_body = {{"data", {"nested", "Some string"}},
{"other", "Another string"}};
const auto serialized_body = jsonrpc::pack(j_body, pack_type);
const auto serialized_body = serdes::pack(j_body, pack_type);
auto [signed_call, signed_req] =
create_signed_request(echo_call, &serialized_body);
@ -892,7 +892,7 @@ TEST_CASE("MinimalEndpointFunction")
auto fail = create_simple_request("failable");
const nlohmann::json j_body = {
{"error", {{"code", err}, {"message", msg}}}};
const auto serialized_body = jsonrpc::pack(j_body, default_pack);
const auto serialized_body = serdes::pack(j_body, default_pack);
const auto [signed_call, signed_req] =
create_signed_request(fail, &serialized_body);
@ -1022,7 +1022,7 @@ TEST_CASE("Explicit commitability")
const nlohmann::json request_body = {{"value", new_value},
{"status", status}};
const auto serialized_body = jsonrpc::pack(request_body, default_pack);
const auto serialized_body = serdes::pack(request_body, default_pack);
request.set_body(&serialized_body);
const auto serialized_request = request.build_request();
@ -1058,7 +1058,7 @@ TEST_CASE("Explicit commitability")
const nlohmann::json request_body = {
{"value", new_value}, {"apply", apply}, {"status", status}};
const auto serialized_body = jsonrpc::pack(request_body, default_pack);
const auto serialized_body = serdes::pack(request_body, default_pack);
request.set_body(&serialized_body);
const auto serialized_request = request.build_request();

Просмотреть файл

@ -8,8 +8,8 @@
#include "kv/test/null_encryptor.h"
#include "node/client_signatures.h"
#include "node/genesis_gen.h"
#include "node/rpc/json_rpc.h"
#include "node/rpc/member_frontend.h"
#include "node/rpc/serdes.h"
#include "node/rpc/user_frontend.h"
#include "node_stub.h"
#include "runtime_config/default_whitelists.h"
@ -26,7 +26,7 @@ extern "C"
using namespace ccfapp;
using namespace ccf;
using namespace std;
using namespace jsonrpc;
using namespace serdes;
using namespace nlohmann;
using TResponse = http::SimpleResponseProcessor::Response;
@ -41,7 +41,7 @@ std::vector<uint8_t> dummy_key_share = {1, 2, 3};
auto encryptor = std::make_shared<kv::NullTxEncryptor>();
constexpr auto default_pack = jsonrpc::Pack::Text;
constexpr auto default_pack = serdes::Pack::Text;
string get_script_path(string name)
{
@ -63,7 +63,7 @@ T parse_response_body(const TResponse& r)
nlohmann::json body_j;
try
{
body_j = jsonrpc::unpack(r.body, jsonrpc::Pack::Text);
body_j = serdes::unpack(r.body, serdes::Pack::Text);
}
catch (const nlohmann::json::parse_error& e)
{
@ -113,7 +113,7 @@ std::vector<uint8_t> create_request(
{
http::Request r(method_name, verb);
const auto body = params.is_null() ? std::vector<uint8_t>() :
jsonrpc::pack(params, default_pack);
serdes::pack(params, default_pack);
r.set_body(&body);
return r.build_request();
}
@ -127,7 +127,7 @@ std::vector<uint8_t> create_signed_request(
http::Request r(method_name, verb);
const auto body = params.is_null() ? std::vector<uint8_t>() :
jsonrpc::pack(params, default_pack);
serdes::pack(params, default_pack);
r.set_body(&body);
http::sign_request(r, kp_);

Просмотреть файл

@ -6,8 +6,8 @@
#include "ds/logger.h"
#include "nlohmann/json.hpp"
#include "node/genesis_gen.h"
#include "node/rpc/json_rpc.h"
#include "node/rpc/node_frontend.h"
#include "node/rpc/serdes.h"
#include "node_stub.h"
#include "tls/pem.h"
#include "tls/verifier.h"
@ -16,7 +16,7 @@
using namespace ccf;
using namespace nlohmann;
using namespace jsonrpc;
using namespace serdes;
extern "C"
{
@ -48,7 +48,7 @@ TResponse frontend_process(
http::Request r(method);
const auto body = json_params.is_null() ?
std::vector<uint8_t>() :
jsonrpc::pack(json_params, Pack::Text);
serdes::pack(json_params, Pack::Text);
r.set_body(&body);
auto serialise_request = r.build_request();
@ -72,7 +72,7 @@ TResponse frontend_process(
template <typename T>
T parse_response_body(const TResponse& r)
{
const auto body_j = jsonrpc::unpack(r.body, jsonrpc::Pack::Text);
const auto body_j = serdes::unpack(r.body, serdes::Pack::Text);
return body_j.get<T>();
}

Просмотреть файл

@ -39,9 +39,9 @@ def run(args):
with primary.client() as uc:
r = uc.get("/node/code")
assert r.result == {
assert r.body == {
"versions": [{"digest": first_code_id, "status": "ACCEPTED"}],
}, r.result
}, r.body
LOG.info("Adding a new node")
new_node = network.create_and_trust_node(args.package, "localhost", args)
@ -71,7 +71,7 @@ def run(args):
with primary.client() as uc:
r = uc.get("/node/code")
versions = sorted(r.result["versions"], key=lambda x: x["digest"])
versions = sorted(r.body["versions"], key=lambda x: x["digest"])
expected = sorted(
[
{"digest": first_code_id, "status": "ACCEPTED"},

Просмотреть файл

@ -43,7 +43,7 @@ def run(args):
LOG.error(f"Failed to connect client {i}")
c = clients[int(random.random() * len(clients))]
check(c.rpc("/app/log/private", {"id": 42, "msg": "foo"}), result=True)
check(c.post("/app/log/private", {"id": 42, "msg": "foo"}), result=True)
assert (
len(clients) >= max_fds - num_fds - 1
@ -64,7 +64,7 @@ def run(args):
LOG.info(f"Connected client {i}")
c = clients[int(random.random() * len(clients))]
check(c.rpc("/app/log/private", {"id": 42, "msg": "foo"}), result=True)
check(c.post("/app/log/private", {"id": 42, "msg": "foo"}), result=True)
assert (
len(clients) >= max_fds - num_fds - 1

Просмотреть файл

@ -35,7 +35,7 @@ def test(network, args, batch_size=100, write_key_divisor=1, write_size_multipli
pre_submit = time.time()
check(
c.rpc(
c.post(
"/app/BATCH_submit",
{
"entries": messages,
@ -50,7 +50,7 @@ def test(network, args, batch_size=100, write_key_divisor=1, write_size_multipli
f"Submitting {batch_size} new keys took {post_submit - pre_submit}s"
)
fetch_response = c.rpc("/app/BATCH_fetch", message_ids)
fetch_response = c.post("/app/BATCH_fetch", message_ids)
if write_key_divisor == 1 and write_size_multiplier == 1:
check(fetch_response, result=messages)

Просмотреть файл

@ -88,7 +88,7 @@ def test_large_messages(network, args):
for p in range(14, 20) if args.consensus == "raft" else range(10, 13):
long_msg = "X" * (2 ** p)
check_commit(
c.rpc("/app/log/private", {"id": log_id, "msg": long_msg}),
c.post("/app/log/private", {"id": log_id, "msg": long_msg}),
result=True,
)
check(
@ -117,7 +117,7 @@ def test_remove(network, args):
for table in ["private", "public"]:
resource = f"/app/log/{table}"
check_commit(
c.rpc(resource, {"id": log_id, "msg": msg}), result=True,
c.post(resource, {"id": log_id, "msg": msg}), result=True,
)
check(c.get(resource, {"id": log_id}), result={"msg": msg})
check(
@ -153,10 +153,9 @@ def test_cert_prefix(network, args):
with primary.client(f"user{user_id}") as c:
log_id = 101
msg = "This message will be prefixed"
c.rpc("/app/log/private/prefix_cert", {"id": log_id, "msg": msg})
c.post("/app/log/private/prefix_cert", {"id": log_id, "msg": msg})
r = c.get("/app/log/private", {"id": log_id})
assert r.result is not None
assert f"CN=user{user_id}" in r.result["msg"]
assert f"CN=user{user_id}" in r.body["msg"], r
else:
LOG.warning(
@ -178,17 +177,15 @@ def test_anonymous_caller(network, args):
log_id = 101
msg = "This message is anonymous"
with primary.client("user4") as c:
r = c.rpc("/app/log/private/anonymous", {"id": log_id, "msg": msg})
assert r.result == True
r = c.post("/app/log/private/anonymous", {"id": log_id, "msg": msg})
assert r.body == True
r = c.get("/app/log/private", {"id": log_id})
assert (
r.error is not None
), "Anonymous user is not authorised to call log/private"
assert r.status == 403, r
with primary.client("user0") as c:
r = c.get("/app/log/private", {"id": log_id})
assert r.result is not None
assert msg in r.result["msg"]
assert msg in r.body["msg"], r
else:
LOG.warning(
f"Skipping {inspect.currentframe().f_code.co_name} as application is not C++"
@ -206,15 +203,14 @@ def test_raw_text(network, args):
log_id = 101
msg = "This message is not in JSON"
with primary.client("user0") as c:
r = c.rpc(
r = c.post(
f"/app/log/private/raw_text/{log_id}",
msg,
headers={"content-type": "text/plain"},
)
assert r.status == http.HTTPStatus.OK.value
r = c.get("/app/log/private", {"id": log_id})
assert r.result is not None
assert msg in r.result["msg"]
assert msg in r.body["msg"], r
else:
LOG.warning(
@ -241,14 +237,14 @@ def test_historical_query(network, args):
with primary.client("user0") as c:
log_id = 10
msg = "This tests historical queries"
record_response = c.rpc("/app/log/private", {"id": log_id, "msg": msg})
record_response = c.post("/app/log/private", {"id": log_id, "msg": msg})
check_commit(record_response, result=True)
view = record_response.view
seqno = record_response.seqno
msg2 = "This overwrites the original message"
check_commit(
c.rpc("/app/log/private", {"id": log_id, "msg": msg2}), result=True
c.post("/app/log/private", {"id": log_id, "msg": msg2}), result=True
)
check(c.get("/app/log/private", {"id": log_id}), result={"msg": msg2})
@ -274,9 +270,7 @@ def test_historical_query(network, args):
retry_after = int(retry_after)
time.sleep(retry_after)
elif get_response.status == http.HTTPStatus.OK:
assert (
get_response.result["msg"] == msg
), f"{get_response.result}"
assert get_response.body["msg"] == msg, get_response
found = True
break
elif get_response.status == http.HTTPStatus.NO_CONTENT:
@ -285,7 +279,7 @@ def test_historical_query(network, args):
)
else:
raise ValueError(
f"Unexpected response status {get_response.status}: {get_response.error}"
f"Unexpected response status {get_response.status}: {get_response.body}"
)
if not found:
@ -318,7 +312,7 @@ def test_forwarding_frontends(network, args):
msg = "forwarded_msg"
log_id = 123
check_commit(
c.rpc("/app/log/private", {"id": log_id, "msg": msg}), result=True,
c.post("/app/log/private", {"id": log_id, "msg": msg}), result=True,
)
check(c.get("/app/log/private", {"id": log_id}), result={"msg": msg})
@ -351,7 +345,7 @@ def test_update_lua(network, args):
remote_node=primary, app_script_path=new_app_file
)
with primary.client("user0") as c:
check(c.rpc("/app/ping"), result="pong")
check(c.post("/app/ping"), result="pong")
LOG.debug("Check that former endpoints no longer exists")
for endpoint in [
@ -359,7 +353,7 @@ def test_update_lua(network, args):
"/app/log/public",
]:
check(
c.rpc(endpoint),
c.post(endpoint),
error=lambda status, msg: status == http.HTTPStatus.NOT_FOUND.value,
)
else:
@ -388,13 +382,8 @@ def test_view_history(network, args):
r = c.get("/node/commit")
check(c)
commit_view = r.result["view"]
commit_seqno = r.result["seqno"]
# Temporarily disable logging of RPCs for readability
rpc_loggers = c.rpc_loggers
c.rpc_loggers = ()
LOG.warning("RPC logging temporarily suppressed")
commit_view = r.body["view"]
commit_seqno = r.body["seqno"]
# Retrieve status for all possible Tx IDs
seqno_to_views = {}
@ -403,14 +392,11 @@ def test_view_history(network, args):
for view in range(1, commit_view + 1):
r = c.get("/node/tx", {"view": view, "seqno": seqno})
check(r)
status = TxStatus(r.result["status"])
status = TxStatus(r.body["status"])
if status == TxStatus.Committed:
views.append(view)
seqno_to_views[seqno] = views
c.rpc_loggers = rpc_loggers
LOG.warning("RPC logging restored")
# Check we have exactly one Tx ID for each seqno
txs_ok = True
for seqno, views in seqno_to_views.items():
@ -486,7 +472,7 @@ def test_tx_statuses(network, args):
with primary.client("user0") as c:
check = ccf.checker.Checker()
r = c.rpc("/app/log/private", {"id": 0, "msg": "Ignored"})
r = c.post("/app/log/private", {"id": 0, "msg": "Ignored"})
check(r)
# Until this tx is globally committed, poll for the status of this and some other
# related transactions around it (and also any historical transactions we're tracking)
@ -507,7 +493,7 @@ def test_tx_statuses(network, args):
for view, seqno in SentTxs.get_all_tx_ids():
r = c.get("/node/tx", {"view": view, "seqno": seqno})
check(r)
status = TxStatus(r.result["status"])
status = TxStatus(r.body["status"])
SentTxs.update_status(view, seqno, status)
if (
status == TxStatus.Committed

Просмотреть файл

@ -52,7 +52,7 @@ def run(args):
txs += json.load(f)
for tx in txs:
r = client.rpc(
r = client.call(
tx["method"],
params=tx["params"],
http_verb=tx.get("verb", "POST"),

Просмотреть файл

@ -46,7 +46,7 @@ def wait_for_seqno_to_commit(seqno, view, nodes):
assert (
r.status == http.HTTPStatus.OK
), f"tx request returned HTTP status {r.status}"
status = TxStatus(r.result["status"])
status = TxStatus(r.body["status"])
if status == TxStatus.Committed:
up_to_date_f.append(f.node_id)
elif status == TxStatus.Invalid:
@ -95,7 +95,7 @@ def run(args):
)
)
with primary.client("user0") as c:
res = c.rpc(
res = c.post(
"/app/log/private",
{
"id": current_view,

Просмотреть файл

@ -38,7 +38,7 @@ def test_quote(network, args, notifications_queue=None, verify=True):
expected_mrenclave = lines[0].strip().split("=")[1]
r = c.get("/node/quote")
quotes = r.result["quotes"]
quotes = r.body["quotes"]
assert len(quotes) == 1
primary_quote = quotes[0]
assert primary_quote["node_id"] == 0
@ -49,7 +49,7 @@ def test_quote(network, args, notifications_queue=None, verify=True):
)
r = c.get("/node/quotes")
quotes = r.result["quotes"]
quotes = r.body["quotes"]
assert len(quotes) == len(network.find_nodes())
for quote in quotes:
mrenclave = quote["mrenclave"]

Просмотреть файл

@ -96,7 +96,7 @@ def run(args):
new_member_proposal.proposer_id
).withdraw(primary, new_member_proposal)
assert response.status == http.HTTPStatus.OK.value
assert response.result["state"] == ProposalState.Withdrawn.value
assert response.body["state"] == ProposalState.Withdrawn.value
withdrawals_issued += 1
(final_proposals, final_votes, final_withdrawals,) = count_governance_operations(

Просмотреть файл

@ -46,7 +46,7 @@ class Consortium:
self.recovery_threshold = len(self.members)
else:
with remote_node.client("member0") as mc:
r = mc.rpc(
r = mc.post(
"/gov/query",
{
"text": """tables = ...
@ -60,7 +60,7 @@ class Consortium:
"""
},
)
for m in r.result or []:
for m in r.body or []:
new_member = infra.member.Member(
m[0], curve, self.common_dir, share_script
)
@ -72,7 +72,7 @@ class Consortium:
self.members.append(new_member)
LOG.info(f"Successfully recovered member {m[0]} with status {m[1]}")
r = mc.rpc(
r = mc.post(
"/gov/query",
{
"text": """tables = ...
@ -80,7 +80,7 @@ class Consortium:
"""
},
)
self.recovery_threshold = r.result["recovery_threshold"]
self.recovery_threshold = r.body["recovery_threshold"]
def activate(self, remote_node):
for m in self.members:
@ -157,7 +157,7 @@ class Consortium:
wait_for_global_commit=wait_for_global_commit,
)
assert response.status == http.HTTPStatus.OK.value
proposal.state = infra.proposal.ProposalState(response.result["state"])
proposal.state = infra.proposal.ProposalState(response.body["state"])
proposal.increment_votes_for()
if proposal.state is not ProposalState.Accepted:
@ -176,9 +176,9 @@ class Consortium:
proposals = []
with remote_node.client(f"member{self.get_any_active_member().member_id}") as c:
r = c.rpc("/gov/query", {"text": script})
r = c.post("/gov/query", {"text": script})
assert r.status == http.HTTPStatus.OK.value
for proposal_id, attr in r.result.items():
for proposal_id, attr in r.body.items():
has_proposer_voted_for = False
for vote in attr["votes"]:
if attr["proposer"] == vote[0]:
@ -203,10 +203,10 @@ class Consortium:
self.vote_using_majority(remote_node, proposal)
with remote_node.client(f"member{self.get_any_active_member().member_id}") as c:
r = c.rpc(
r = c.post(
"/gov/read", {"table": "ccf.nodes", "key": node_to_retire.node_id}
)
assert r.result["status"] == infra.node.NodeStatus.RETIRED.name
assert r.body["status"] == infra.node.NodeStatus.RETIRED.name
def trust_node(self, remote_node, node_id):
if not self._check_node_exists(
@ -314,10 +314,10 @@ class Consortium:
check_commit(r)
if submitted_shares_count >= self.recovery_threshold:
assert "End of recovery procedure initiated" in r.result
assert "End of recovery procedure initiated" in r.body
break
else:
assert "End of recovery procedure initiated" not in r.result
assert "End of recovery procedure initiated" not in r.body
def set_recovery_threshold(self, remote_node, recovery_threshold):
proposal_body, careful_vote = self.proposal_generator.set_recovery_threshold(
@ -352,7 +352,7 @@ class Consortium:
f"member{self.get_any_active_member().member_id}",
request_timeout=(30 if pbft_open else 3),
) as c:
r = c.rpc(
r = c.post(
"/gov/query",
{
"text": """tables = ...
@ -374,8 +374,8 @@ class Consortium:
"""
},
)
current_status = r.result["status"]
current_cert = array.array("B", r.result["cert"]).tobytes()
current_status = r.body["status"]
current_cert = array.array("B", r.body["cert"]).tobytes()
expected_cert = open(
os.path.join(self.common_dir, "networkcert.pem"), "rb"
@ -389,10 +389,10 @@ class Consortium:
def _check_node_exists(self, remote_node, node_id, node_status=None):
with remote_node.client(f"member{self.get_any_active_member().member_id}") as c:
r = c.rpc("/gov/read", {"table": "ccf.nodes", "key": node_id})
r = c.post("/gov/read", {"table": "ccf.nodes", "key": node_id})
if r.error is not None or (
node_status and r.result["status"] != node_status.name
if r.status != 200 or (
node_status and r.body["status"] != node_status.name
):
return False

Просмотреть файл

@ -152,7 +152,7 @@ def cli_args(add=lambda x: None, parser=None, accept_unknown=False):
"--ledger-recovery-timeout",
help="On recovery, maximum timeout (s) while reading the ledger",
type=int,
default=10,
default=30,
)
parser.add_argument(
"--ledger-chunk-max-bytes",

Просмотреть файл

@ -1,29 +0,0 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the Apache 2.0 License.
from enum import IntEnum
# Values defined in node/rpc/jsonrpc.h
class ErrorCode(IntEnum):
# Standard JSON RPC errors
PARSE_ERROR = -32700
INVALID_REQUEST = -32600
METHOD_NOT_FOUND = -32601
INVALID_PARAMS = -32602
INTERNAL_ERROR = -32603
# CCF-specific errors
SERVER_ERROR_START = -32000
TX_NOT_PRIMARY = -32001
TX_FAILED_TO_REPLICATE = -32002
SCRIPT_ERROR = -32003
INSUFFICIENT_RIGHTS = -32004
TX_PRIMARY_UNKNOWN = -32005
RPC_NOT_SIGNED = -32006
INVALID_CLIENT_SIGNATURE = -32007
INVALID_CALLER_ID = -32008
CODE_ID_NOT_FOUND = -32009
CODE_ID_RETIRED = -32010
RPC_NOT_FORWARDED = -32011
QUOTE_NOT_VERIFIED = -32012
SERVER_ERROR_END = -32099

Просмотреть файл

@ -101,11 +101,11 @@ class LoggingTxs:
f"Private message at index {self.next_priv_index}"
)
pub_msg = f"Public message at index {self.next_pub_index}"
rep_priv = uc.rpc(
rep_priv = uc.post(
"/app/log/private",
{"id": self.next_priv_index, "msg": priv_msg,},
)
rep_pub = uc.rpc(
rep_pub = uc.post(
"/app/log/public",
{"id": self.next_pub_index, "msg": pub_msg,},
)

Просмотреть файл

@ -67,14 +67,14 @@ class Member:
def propose(self, remote_node, proposal, has_proposer_voted_for=True):
with remote_node.client(f"member{self.member_id}") as mc:
r = mc.rpc("/gov/proposals", proposal, signed=True,)
r = mc.post("/gov/proposals", proposal, signed=True,)
if r.status != http.HTTPStatus.OK.value:
raise infra.proposal.ProposalNotCreated(r)
return infra.proposal.Proposal(
proposer_id=self.member_id,
proposal_id=r.result["proposal_id"],
state=infra.proposal.ProposalState(r.result["state"]),
proposal_id=r.body["proposal_id"],
state=infra.proposal.ProposalState(r.body["state"]),
has_proposer_voted_for=has_proposer_voted_for,
)
@ -82,20 +82,20 @@ class Member:
self, remote_node, proposal, accept=True, wait_for_global_commit=True,
):
with remote_node.client(f"member{self.member_id}") as mc:
r = mc.rpc(
r = mc.post(
f"/gov/proposals/{proposal.proposal_id}/votes",
params=proposal.vote_for,
signed=True,
)
if r.error is not None:
if r.status != 200:
return r
# If the proposal was accepted, wait for it to be globally committed
# This is particularly useful for the open network proposal to wait
# until the global hook on the SERVICE table is triggered
if (
r.result["state"] == infra.proposal.ProposalState.Accepted.value
r.body["state"] == infra.proposal.ProposalState.Accepted.value
and wait_for_global_commit
):
with remote_node.client() as mc:
@ -109,24 +109,24 @@ class Member:
def withdraw(self, remote_node, proposal):
with remote_node.client(f"member{self.member_id}") as c:
r = c.rpc(f"/gov/proposals/{proposal.proposal_id}/withdraw", signed=True)
r = c.post(f"/gov/proposals/{proposal.proposal_id}/withdraw", signed=True)
if r.status == http.HTTPStatus.OK.value:
proposal.state = infra.proposal.ProposalState.Withdrawn
return r
def update_ack_state_digest(self, remote_node):
with remote_node.client(f"member{self.member_id}") as mc:
r = mc.rpc("/gov/ack/update_state_digest")
assert r.error is None, f"Error ack/update_state_digest: {r.error}"
return bytearray(r.result["state_digest"])
r = mc.post("/gov/ack/update_state_digest")
assert r.status == 200, f"Error ack/update_state_digest: {r}"
return bytearray(r.body["state_digest"])
def ack(self, remote_node):
state_digest = self.update_ack_state_digest(remote_node)
with remote_node.client(f"member{self.member_id}") as mc:
r = mc.rpc(
r = mc.post(
"/gov/ack", params={"state_digest": list(state_digest)}, signed=True
)
assert r.error is None, f"Error ACK: {r.error}"
assert r.status == 200, f"Error ACK: {r}"
self.status = MemberStatus.ACTIVE
return r
@ -141,10 +141,8 @@ class Member:
defunct_network_enc_pubk,
)
nonce_bytes = base64.b64decode(r.result["nonce"])
encrypted_share_bytes = base64.b64decode(
r.result["encrypted_recovery_share"]
)
nonce_bytes = base64.b64decode(r.body["nonce"])
encrypted_share_bytes = base64.b64decode(r.body["encrypted_recovery_share"])
return ctx.decrypt(encrypted_share_bytes, nonce_bytes)
def get_and_submit_recovery_share(self, remote_node, defunct_network_enc_pubk):

Просмотреть файл

@ -137,9 +137,9 @@ class Network:
with primary.client() as nc:
r = nc.get("/node/primary_info")
first_node_id = r.result["primary_id"]
assert (r.result["primary_host"] == primary.host) and (
int(r.result["primary_port"]) == primary.rpc_port
first_node_id = r.body["primary_id"]
assert (r.body["primary_host"] == primary.host) and (
int(r.body["primary_port"]) == primary.rpc_port
), "Primary is not the node that just started"
for n in self.nodes:
n.node_id = n.node_id + first_node_id
@ -489,8 +489,7 @@ class Network:
try:
with node.client(connection_timeout=timeout) as c:
r = c.get("/node/state")
LOG.info(r.result)
if r.result["state"] == state:
if r.body["state"] == state:
break
except ConnectionRefusedError:
pass
@ -519,12 +518,12 @@ class Network:
with node.client(request_timeout=request_timeout) as c:
try:
res = c.get("/node/primary_info")
if res.error is None:
primary_id = res.result["primary_id"]
view = res.result["current_view"]
if res.status == 200:
primary_id = res.body["primary_id"]
view = res.body["current_view"]
break
else:
assert "Primary unknown" in res.error, res.error
assert "Primary unknown" in res.body, res
except CCFConnectionException:
pass
if primary_id is not None:
@ -563,8 +562,8 @@ class Network:
while time.time() < end_time:
with primary.client() as c:
resp = c.get("/node/commit")
seqno = resp.result["seqno"]
view = resp.result["view"]
seqno = resp.body["seqno"]
view = resp.body["view"]
if seqno != 0:
break
time.sleep(0.1)
@ -577,10 +576,10 @@ class Network:
for node in self.get_joined_nodes():
with node.client() as c:
resp = c.get("/node/tx", {"view": view, "seqno": seqno})
if resp.error is not None:
if resp.status != 200:
# Node may not have joined the network yet, try again
break
status = TxStatus(resp.result["status"])
status = TxStatus(resp.body["status"])
if status == TxStatus.Committed:
caught_up_nodes.append(node)
elif status == TxStatus.Invalid:

Просмотреть файл

@ -236,8 +236,8 @@ class Node:
with self.client(connection_timeout=timeout) as nc:
rep = nc.get("/node/commit")
assert (
rep.error is None and rep.result is not None
), f"An error occured after node {self.node_id} joined the network: {rep.error}"
rep.status == 200
), f"An error occured after node {self.node_id} joined the network: {rep.body}"
except ccf.clients.CCFConnectionException:
raise TimeoutError(f"Node {self.node_id} failed to join the network")

Просмотреть файл

@ -54,8 +54,7 @@ class TxRates:
def process_next(self):
with self.primary.client() as client:
rv = client.get("/node/commit")
result = rv.to_dict()
next_commit = result["result"]["seqno"]
next_commit = rv.body["seqno"]
more_to_process = self.commit != next_commit
self.commit = next_commit
@ -64,13 +63,11 @@ class TxRates:
def get_metrics(self):
with self.primary.client() as client:
rv = client.get("/node/metrics")
result = rv.to_dict()
result = result["result"]
self.all_metrics = result
self.all_metrics = rv.body
all_rates = []
all_durations = []
rates = result.get("tx_rates")
rates = self.all_metrics.get("tx_rates")
if rates is None:
LOG.info("No tx rate metrics found...")
else:
@ -79,7 +76,7 @@ class TxRates:
all_durations.append(float(rates[key]["duration"]))
self.tx_rates_data = all_rates
histogram = result.get("histogram")
histogram = self.all_metrics.get("histogram")
if histogram is None:
LOG.info("No histogram metrics found...")
else:

Просмотреть файл

@ -42,7 +42,7 @@ def update_view_info(network, view_info):
def get_node_local_commit(node):
with node.client() as c:
r = c.get("/node/commit")
return r.result["seqno"], r.global_commit
return r.body["seqno"], r.global_commit
def wait_for_late_joiner(old_node, late_joiner, strict=False, timeout=60):

Просмотреть файл

@ -15,12 +15,8 @@ const baseURL = `https://${__ENV.HOST}/`;
export function setup()
{
const body = JSON.stringify({
jsonrpc: "2.0",
method: "users/log/private",
params: {
id: 0,
msg: "Unique message: d41d8cd98f00b204e9800998ecf8427e"
}
id: 0,
msg: "Unique message: d41d8cd98f00b204e9800998ecf8427e"
});
const params = {headers: { "Content-Type": "application/json" }};

Просмотреть файл

@ -48,7 +48,7 @@ def test_add_member(network, args):
)
assert False, "New accepted members are not given recovery shares"
except infra.member.NoRecoveryShareFound as e:
assert e.response.error == "Only active members are given recovery shares"
assert e.response.body == "Only active members are given recovery shares"
new_member.ack(primary)
@ -79,7 +79,7 @@ def test_missing_signature(network, args):
primary, _ = network.find_primary()
member = network.consortium.get_any_active_member()
with primary.client(f"member{member.member_id}") as mc:
r = mc.rpc("/gov/proposals", signed=False)
r = mc.post("/gov/proposals", signed=False)
assert r.status == http.HTTPStatus.UNAUTHORIZED, r.status
www_auth = "www-authenticate"
assert www_auth in r.headers, r.headers
@ -290,7 +290,7 @@ def run(args):
assert False, "Retired member cannot make a new proposal"
except infra.proposal.ProposalNotCreated as e:
assert e.response.status == http.HTTPStatus.FORBIDDEN.value
assert e.response.error == "Member is not active"
assert e.response.body == "Member is not active"
LOG.debug("New member should still be able to make a new proposal")
new_proposal = new_member.propose(primary, proposal_trust_0)

Просмотреть файл

@ -25,26 +25,26 @@ def test(network, args, notifications_queue=None):
LOG.info("Write/Read on primary")
with primary.client("user0") as c:
r = c.rpc("/app/log/private", {"id": 42, "msg": msg})
r = c.post("/app/log/private", {"id": 42, "msg": msg})
check_commit(r, result=True)
check(c.get("/app/log/private", {"id": 42}), result={"msg": msg})
for _ in range(10):
c.rpc(
c.post(
"/app/log/private", {"id": 43, "msg": "Additional messages"},
)
check_commit(
c.rpc("/app/log/private", {"id": 43, "msg": "A final message"}),
c.post("/app/log/private", {"id": 43, "msg": "A final message"}),
result=True,
)
r = c.get("/app/receipt", {"commit": r.seqno})
check(
c.rpc("/app/receipt/verify", {"receipt": r.result["receipt"]}),
c.post("/app/receipt/verify", {"receipt": r.body["receipt"]}),
result={"valid": True},
)
invalid = r.result["receipt"]
invalid = r.body["receipt"]
invalid[-3] += 1
check(
c.rpc("/app/receipt/verify", {"receipt": invalid}),
c.post("/app/receipt/verify", {"receipt": invalid}),
result={"valid": False},
)

Просмотреть файл

@ -16,7 +16,7 @@ def check_can_progress(node, timeout=3):
uc.post("/app/log/private", {"id": 42, "msg": "Hello world"})
end_time = time.time() + timeout
while time.time() < end_time:
if c.get("/node/commit").result["seqno"] > r.result["seqno"]:
if c.get("/node/commit").body["seqno"] > r.body["seqno"]:
return
time.sleep(0.1)
assert False, f"Stuck at {r}"

Просмотреть файл

@ -36,7 +36,7 @@ def run(args):
check(
list_response, error=lambda status, msg: status == http.HTTPStatus.OK.value
)
methods = list_response.result["methods"]
methods = list_response.body["methods"]
all_methods.extend(methods)
for method in methods:
@ -49,8 +49,8 @@ def run(args):
error=lambda status, msg: status == http.HTTPStatus.OK.value,
)
if schema_response.result is not None:
for verb, schema_element in schema_response.result.items():
if schema_response.body is not None:
for verb, schema_element in schema_response.body.items():
for schema_type in ["params", "result"]:
element_name = "{}_schema".format(schema_type)
element = schema_element[element_name]

Просмотреть файл

@ -52,7 +52,7 @@ def supports_methods(*methods):
primary, _ = network.find_primary()
with primary.client("user0") as c:
response = c.get("/app/api")
supported_methods = response.result["methods"]
supported_methods = response.body["methods"]
missing = {*methods}.difference(supported_methods)
if missing:
concat = ", ".join(missing)
@ -90,9 +90,9 @@ def sufficient_member_count():
def can_kill_n_nodes(nodes_to_kill_count):
def check(network, args, *nargs, **kwargs):
primary, _ = network.find_primary()
with primary.client(identity="member0") as c:
r = c.rpc(
"query",
with primary.client("member0") as c:
r = c.post(
"gov/query",
{
"text": """tables = ...
trusted_nodes_count = 0
@ -106,7 +106,7 @@ def can_kill_n_nodes(nodes_to_kill_count):
},
)
trusted_nodes_count = r.result
trusted_nodes_count = r.body
running_nodes_count = len(network.get_joined_nodes())
would_leave_nodes_count = running_nodes_count - nodes_to_kill_count
minimum_nodes_to_run_count = ceil((trusted_nodes_count + 1) / 2)

Просмотреть файл

@ -21,8 +21,8 @@ def test(network, args, notifications_queue=None):
LOG.info("Write on primary")
with primary.client("user0", ws=True) as c:
for i in [1, 50, 500]:
r = c.rpc("/app/log/private", {"id": 42, "msg": msg * i})
assert r.result == True, r.result
r = c.post("/app/log/private", {"id": 42, "msg": msg * i})
assert r.body == True, r
# Before we start sending transactions to the secondary,
# we want to wait for its app frontend to be open, which is
@ -31,7 +31,7 @@ def test(network, args, notifications_queue=None):
end_time = time.time() + 10
with other.client("user0") as nc:
while time.time() < end_time:
r = nc.rpc("/app/log/private", {"id": 42, "msg": msg * i})
r = nc.post("/app/log/private", {"id": 42, "msg": msg * i})
if r.status == 200:
break
else:
@ -41,8 +41,8 @@ def test(network, args, notifications_queue=None):
LOG.info("Write on secondary through forwarding")
with other.client("user0", ws=True) as c:
for i in [1, 50, 500]:
r = c.rpc("/app/log/private", {"id": 42, "msg": msg * i})
assert r.result == True, r.result
r = c.post("/app/log/private", {"id": 42, "msg": msg * i})
assert r.body == True, r
return network