Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix historical TX requests for previous epochs during recovery #6507

Merged
22 changes: 22 additions & 0 deletions src/node/historical_queries_adapter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -509,6 +509,28 @@ namespace ccf::historical
}
}

// If recovery in progress, prohibit any historical queries for previous
// epochs.
achamayou marked this conversation as resolved.
Show resolved Hide resolved
auto service = args.tx.template ro<ccf::Service>(Tables::SERVICE);
auto active_service = service->get();
if (active_service && active_service->status != ServiceStatus::OPEN)
{
if (
active_service->current_service_create_txid &&
target_tx_id.view < active_service->current_service_create_txid->view)
{
auto reason = fmt::format(
"Historical transaction {} is not signed by the current service "
"identity key and can't be retrieved until recovery is complete.",
maxtropets marked this conversation as resolved.
Show resolved Hide resolved
target_tx_id.to_str());
ehandler(
HistoricalQueryErrorCode::TransactionInvalid,
std::move(reason),
args);
return;
}
}

// We need a handle to determine whether this request is the 'same' as a
// previous one. For simplicity we use target_tx_id.seqno. This means we
// keep a lot of state around for old requests! It should be cleaned up
Expand Down
22 changes: 21 additions & 1 deletion tests/recovery.py
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,11 @@ def test_recover_service_with_wrong_identity(network, args):
network.save_service_identity(args)
first_service_identity_file = args.previous_service_identity_file

with old_primary.client() as c:
last_view, last_seq = (
c.get('/node/commit').body.json()['transaction_id'].split('.')
)

network.stop_all_nodes()

current_ledger_dir, committed_ledger_dirs = old_primary.get_ledger()
Expand Down Expand Up @@ -254,8 +259,23 @@ def test_recover_service_with_wrong_identity(network, args):
snapshots_dir=snapshots_dir,
)

recovered_network.recover(args)
primary, _ = recovered_network.find_primary()
with primary.client() as cli:
curr_view, curr_seq = (
maxtropets marked this conversation as resolved.
Show resolved Hide resolved
cli.get('/node/commit').body.json()['transaction_id'].split('.')
)
response = cli.get(f"/node/receipt?transaction_id={last_view}.{last_seq}")
assert response.status_code == http.HTTPStatus.NOT_FOUND, response
assert (
"not signed by the current servic"
maxtropets marked this conversation as resolved.
Show resolved Hide resolved
in response.body.json()["error"]["message"]
), response

curr_receipt = primary.get_receipt(curr_view, curr_seq)
# verify_receipt(curr_receipt.json(), network.cert)
# verify_receipt fails - missing path?..
maxtropets marked this conversation as resolved.
Show resolved Hide resolved

recovered_network.recover(args)
return recovered_network


Expand Down
Loading