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

Correct and enforce schema on CBOR proofs #6520

Merged
merged 9 commits into from
Oct 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions cddl/ccf-tree-alg.cddl
Original file line number Diff line number Diff line change
@@ -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)
]
4 changes: 2 additions & 2 deletions src/node/historical_queries_adapter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<uint8_t> hash{node.hash};

QCBOREncode_OpenArray(&ctx);
QCBOREncode_AddInt64(&ctx, dir);
QCBOREncode_AddBool(&ctx, dir);
QCBOREncode_AddBytes(&ctx, {hash.data(), hash.size()});
QCBOREncode_CloseArray(&ctx);
}
Expand Down
17 changes: 14 additions & 3 deletions src/node/test/historical_queries.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -314,8 +314,19 @@ MerkleProofData decode_merkle_proof(const std::vector<uint8_t>& encoded)
std::pair<int64_t, std::vector<uint8_t>> 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);
Expand Down Expand Up @@ -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<uint8_t> hash{node.hash};

Expand Down
32 changes: 10 additions & 22 deletions tests/e2e_logging.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@
import threading
import copy
import programmability
import cbor2
import e2e_common_endpoints
import subprocess

from loguru import logger as LOG

Expand Down Expand Up @@ -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
Expand Down