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

Bug in sDictGet: Premature Exit Code 9 for Missing Keys #1468

Open
ipromise2324 opened this issue Jan 9, 2025 · 1 comment
Open

Bug in sDictGet: Premature Exit Code 9 for Missing Keys #1468

ipromise2324 opened this issue Jan 9, 2025 · 1 comment

Comments

@ipromise2324
Copy link

ipromise2324 commented Jan 9, 2025

Background

While using Tolk to write code for parsing exotic cells and verifying the Merkle root before retrieving data from a dictionary, I discovered an unusual issue. When the specified key does not exist in the dictionary, and the dictionary contains more than one key-value pair, the function prematurely throws exit code 9 instead of returning 0 or -1 via the second parameter of sDictGet to indicate whether the key exists in the dictionary.

This inconsistency in the error behavior and its deviation from the sDictGet specification makes it difficult for users to handle errors properly.

Detailed test code can be found in this repository

Description

Here, I will explain my experimental process. First, I wrote a tolk contract and tested it using the merkleAmount(). The merkleAmount function takes three parameters: key: slice, merkleRoot: int, and exoticCell: cell. The function parses the exoticCell, verifies the Merkle root, and retrieves the merkleDict. It then uses the key variable to check whether the key exists in the merkleDict. If the key does not exist, the function throws ERROR_KEY_NOT_EXIST (exit code 1003). If the key exists, the corresponding value is returned. The code can be seen in the snippet below:

image

Test Process:

  1. First Test:
    In the first test, I created a dictionary and added two entries: user0 and user1. A Merkle root and user0's Merkle proof were generated. Then, I tested with an otherAddress that does not exist in the dictionary.
    Expected behavior: Since otherAddress is not in the dictionary, sDictGet should return isKeyExist = 0. This value would then trigger the assert statement assert(isKeyExist, ERROR_KEY_NOT_EXIST);, resulting in ERROR_KEY_NOT_EXIST being thrown.
    Actual result: Before sDictGet could return its result, the function prematurely threw exit code 9, which did not match the expected behavior.

    Test Code:
    image

    Result:
    image

  2. Second Test:
    In this test, I modified the first test by removing user1 from the dictionary. Using the same otherAddress for testing, the function correctly returned isKeyExist = 0 from sDictGet, allowing the assert statement to successfully throw ERROR_KEY_NOT_EXIST (exit code 1003).

    Test Code:
    image

    Result:
    image

  3. Third Test:
    This test confirmed that when the key exists in the dictionary, the function correctly retrieves and returns the associated value.

    Test Code:
    image

    Result:
    image

Environments

@ton/blueprint": "^0.27.0

Hardware Info

MacOS (Macbook M4 pro 2024) built-in SSD.

@EmelyanenkoK
Copy link
Member

It is expected behavior.

In full (not pruned) dictionary we can tell whether specific index is present or not.
But when dictionary is pruned it is not possible, there maybe no information about it at all: imagine dictionary where all branches are pruned. When we try to cal dict operation on the pruned branch, for both cases (key actually exists in dict but pruned, or not exists at all) exception is thrown.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants