From 0b466fd309e560f3a5ec9b99451c21c6b7aaed0a Mon Sep 17 00:00:00 2001 From: Amaury Chamayou Date: Tue, 8 Oct 2024 13:24:07 +0100 Subject: [PATCH] Correct and enforce schema on CBOR proofs (#6520) --- cddl/ccf-tree-alg.cddl | 15 ++++++++++++ src/node/historical_queries_adapter.cpp | 4 ++-- src/node/test/historical_queries.cpp | 17 ++++++++++--- tests/e2e_logging.py | 32 ++++++++----------------- 4 files changed, 41 insertions(+), 27 deletions(-) create mode 100644 cddl/ccf-tree-alg.cddl diff --git a/cddl/ccf-tree-alg.cddl b/cddl/ccf-tree-alg.cddl new file mode 100644 index 000000000000..2ef62e1066d7 --- /dev/null +++ b/cddl/ccf-tree-alg.cddl @@ -0,0 +1,15 @@ +ccf-inclusion-proof = { + &(leaf: 1) => ccf-leaf + &(path: 2) => [+ ccf-proof-element] +} + +ccf-leaf = [ + internal-transaction-hash: bstr .size 32 ; a string of HASH_SIZE(32) bytes + internal-evidence: tstr .size (1..1024) ; a string of at most 1024 bytes + data-hash: bstr .size 32 ; a string of HASH_SIZE(32) bytes +] + +ccf-proof-element = [ + left: bool ; position of the element + hash: bstr .size 32 ; hash of the proof element (string of HASH_SIZE(32) bytes) +] diff --git a/src/node/historical_queries_adapter.cpp b/src/node/historical_queries_adapter.cpp index 97a429171d8e..ae916bc9082b 100644 --- a/src/node/historical_queries_adapter.cpp +++ b/src/node/historical_queries_adapter.cpp @@ -42,12 +42,12 @@ namespace &ctx, ccf::MerkleProofLabel::MERKLE_PROOF_PATH_LABEL); for (const auto& node : path) { - const int64_t dir = + const bool dir = (node.direction == ccf::HistoryTree::Path::Direction::PATH_LEFT); std::vector hash{node.hash}; QCBOREncode_OpenArray(&ctx); - QCBOREncode_AddInt64(&ctx, dir); + QCBOREncode_AddBool(&ctx, dir); QCBOREncode_AddBytes(&ctx, {hash.data(), hash.size()}); QCBOREncode_CloseArray(&ctx); } diff --git a/src/node/test/historical_queries.cpp b/src/node/test/historical_queries.cpp index 9a8f9e84a47c..5be0c1e14725 100644 --- a/src/node/test/historical_queries.cpp +++ b/src/node/test/historical_queries.cpp @@ -314,8 +314,19 @@ MerkleProofData decode_merkle_proof(const std::vector& encoded) std::pair> path_item; REQUIRE(QCBORDecode_GetNext(&ctx, &item) == QCBOR_SUCCESS); - REQUIRE(item.uDataType == QCBOR_TYPE_INT64); - path_item.first = item.val.int64; + if (item.uDataType == CBOR_SIMPLEV_TRUE) + { + path_item.first = true; + } + else if (item.uDataType == CBOR_SIMPLEV_FALSE) + { + path_item.first = false; + } + else + { + // Not a valid CBOR boolean + REQUIRE(false); + } REQUIRE(QCBORDecode_GetNext(&ctx, &item) == QCBOR_SUCCESS); REQUIRE(item.uDataType == QCBOR_TYPE_BYTE_STRING); @@ -1972,7 +1983,7 @@ TEST_CASE("Valid merkle proof from receipts") auto it = decoded.path.begin(); for (const auto& node : *historical_state->receipt->path) { - const int64_t dir = + const bool dir = (node.direction == ccf::HistoryTree::Path::Direction::PATH_LEFT); std::vector hash{node.hash}; diff --git a/tests/e2e_logging.py b/tests/e2e_logging.py index e9d443ac0505..48e25b7846b3 100644 --- a/tests/e2e_logging.py +++ b/tests/e2e_logging.py @@ -36,8 +36,8 @@ import threading import copy import programmability -import cbor2 import e2e_common_endpoints +import subprocess from loguru import logger as LOG @@ -932,27 +932,15 @@ def test_cbor_merkle_proof(network, args): ) if r.status_code == http.HTTPStatus.OK: cbor_proof = r.body.data() - proof = cbor2.loads(cbor_proof) - assert 1 in proof - leaf = proof[1] - assert len(leaf) == 3 - assert isinstance(leaf[0], bytes) # bstr write_set_digest - assert len(leaf[0]) == 32 - assert isinstance(leaf[1], str) # tstr commit_evidence - assert len(leaf[1]) < 1024 - assert isinstance(leaf[2], bytes) # bstr claims_digest - assert len(leaf[2]) == 32 - # path - assert 2 in proof - path = proof[2] - assert isinstance(path, list) - for node in path: - assert isinstance(node, list) - assert len(node) == 2 - assert isinstance(node[0], int) - assert node[0] in {0, 1} # boolean left - assert isinstance(node[1], bytes) # bstr intermediary digest - assert len(node[1]) == 32 + cbor_proof_filename = os.path.join( + network.common_dir, f"proof_{txid}.cbor" + ) + with open(cbor_proof_filename, "wb") as f: + f.write(cbor_proof) + subprocess.run( + ["cddl", "../cddl/ccf-tree-alg.cddl", "v", cbor_proof_filename], + check=True, + ) found_proof = True LOG.debug(f"Checked CBOR Merkle proof for txid {txid}") break