Skip to content

Commit 3713c85

Browse files
authored
[release/6.x] Cherry pick: Logging nulled snapshots (#7298) (#7303)
1 parent 8692580 commit 3713c85

File tree

4 files changed

+63
-1
lines changed

4 files changed

+63
-1
lines changed

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,14 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
66
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
77

8+
## [6.0.13]
9+
10+
[6.0.13]: https://github.com/microsoft/CCF/releases/tag/ccf-6.0.13
11+
12+
### Added
13+
14+
- Better logging of invalid snapshots
15+
816
## [6.0.12]
917

1018
[6.0.12]: https://github.com/microsoft/CCF/releases/tag/ccf-6.0.12

python/pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
44

55
[project]
66
name = "ccf"
7-
version = "6.0.12"
7+
version = "6.0.13"
88
authors = [
99
{ name="CCF Team", email="CCF-Sec@microsoft.com" },
1010
]

src/node/snapshot_serdes.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,11 @@ namespace ccf
5050
auto store_snapshot_size =
5151
sizeof(ccf::kv::SerialisedEntryHeader) + tx_hdr.size;
5252

53+
if (tx_hdr.size == 0)
54+
{
55+
throw std::logic_error("Snapshot transaction size should not be zero");
56+
}
57+
5358
auto receipt_data = data + store_snapshot_size;
5459
auto receipt_size = size - store_snapshot_size;
5560

@@ -58,6 +63,20 @@ namespace ccf
5863
throw std::logic_error("No receipt included in snapshot");
5964
}
6065

66+
LOG_INFO_FMT("Deserialising snapshot receipt (size: {}).", receipt_size);
67+
constexpr size_t max_printed_size = 1024;
68+
if (receipt_size > max_printed_size)
69+
{
70+
LOG_INFO_FMT(
71+
"Receipt size ({}) exceeds max printed size ({}), only printing "
72+
"first {} bytes",
73+
receipt_size,
74+
max_printed_size,
75+
max_printed_size);
76+
}
77+
auto printed_size = std::min<size_t>(receipt_size, max_printed_size);
78+
LOG_INFO_FMT("{}", ds::to_hex(receipt_data, receipt_data + printed_size));
79+
6180
auto j = nlohmann::json::parse(receipt_data, receipt_data + receipt_size);
6281
auto receipt_p = j.get<ReceiptPtr>();
6382
auto receipt = std::dynamic_pointer_cast<ccf::ProofReceipt>(receipt_p);

tests/e2e_operations.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,40 @@ def test_empty_snapshot(network, args):
395395
)
396396

397397

398+
def test_nulled_snapshot(network, args):
399+
400+
with tempfile.TemporaryDirectory() as snapshots_dir:
401+
LOG.debug(f"Using {snapshots_dir} as snapshots directory")
402+
403+
snapshot_name = "snapshot_1000_1500.committed"
404+
405+
with open(
406+
os.path.join(snapshots_dir, snapshot_name), "wb+"
407+
) as temp_empty_snapshot:
408+
409+
LOG.debug(f"Created empty snapshot {temp_empty_snapshot.name}")
410+
temp_empty_snapshot.write(b"\x00" * 64)
411+
412+
LOG.info(
413+
"Attempt to join a node using the corrupted snapshot copy (should fail)"
414+
)
415+
new_node = network.create_node("local://localhost")
416+
failed = False
417+
try:
418+
network.join_node(
419+
new_node,
420+
args.package,
421+
args,
422+
snapshots_dir=snapshots_dir,
423+
)
424+
except Exception as e:
425+
failed = True
426+
LOG.info(f"Node failed to join as expected: {e}")
427+
428+
# (Existing assertion logic retained)
429+
assert failed, "Node should not have joined successfully"
430+
431+
398432
def split_all_ledger_files_in_dir(input_dir, output_dir):
399433
# A ledger file can only be split at a seqno that contains a signature
400434
# (so that all files end on a signature that verifies their integrity).
@@ -486,6 +520,7 @@ def run_file_operations(args):
486520
test_large_snapshot(network, args)
487521
test_snapshot_access(network, args)
488522
test_empty_snapshot(network, args)
523+
test_nulled_snapshot(network, args)
489524

490525
primary, _ = network.find_primary()
491526
# Scoped transactions are not handled by historical range queries

0 commit comments

Comments
 (0)