Info

Download ZIP (1.3 MB)

Testing and Issues

You can test this entry and submit issues during the testing period of the TON Trustless Bridge Challenge contest.

Entries with serious issues will not be able to win the contest, but even minor issues might be important for overall results.

Voting

39
by rating

Issues

Great work on your implementation!

We noticed a potential issue with signature validation: in your `parse_validator_set` function, you load the weight using `int total_weight = cs~load_uint(64);`, which represents the weight of all validators—not just the masterchain validators. The 2/3 threshold should be based solely on the main validators’ weight. This discrepancy could lead to cases where a block with valid signatures is rejected because the signing weight is less than 2/3 of the total validators’ weight, even though it exceeds 2/3 of the main validators’ weight.
3
A
Adam Ton Feb 5 at 22:47
it's impossible to check block signatures on tvm they are signature of a message that is 544 bits the fuction you used will hash the message before verifying (intended for check external messages that are normally hashed in 256bit) so they are two options either you did not test it or you just put it there in case it goes unseen by judges, when i found out about it I dropped the context .
1
Subtle Swallow Feb 6 at 08:22
Block's signatures checking is working correctly. It is approved by both unit tests and examples of blockchain transactions (see readme file to check by yourself)
2. Consider an adversarial scenario where a malicious group of current validators publishes a starting key block with an arbitrary next validator set (e.g., reappointing themselves). Since they are the ones signing the block, your contract wouldn't be able to detect this manipulation unless it had stored the next_validators set from the previous transitioning key block. Without this safeguard, the contract state could be corrupted, affecting functionality.

This is why PoS blockchains include a transition period, ensuring the next validator set is known before the current set’s term ends, preventing such attacks.

Looking forward to your thoughts!
macOS
1
Subtle Swallow Feb 7 at 16:17
My contract only checks blocks of the current epoch (that was the task). It can't check blocks of the previous epoch, including the "transition block".
If a group of validators with a total weight greater than 2/3 want to do something, they will. No one can stop them.
The parameters utime_since and utime_until are not law. There are many situations when the validator set can work longer.
Both objections accepted.
1
Hey! A great work!

Would like to highlight some points.

In `check_validator_signatures` there is no check if given pubkey is used more than once. So having only one valid signature it is possible to achieve any given required weight by repeating it multiple times in `check_block` message. Notice, that in ton-blockchain code you referenced there actualy IS a protection from this issue present -- they track used indices in `seen` variable.

It is possible to make `check_transaction` message with such specific coins amount that gas will be exhausted during lite-client's `check_block`. In this case `transaction-checker` won't receive neither response nor bounce from lite-client, and `g_transactions` will store this pending query record forever and grow storage size over time.
Subtle Swallow Feb 8 at 11:02
Thanks a lot for the comments!
In `check_validator_signatures` I use a validator's pubkey as a hash map key so it's impossible to have more than one signature for each validator.


Yes. it is possible that storage of `check_transaction` will grow in such cases. But attacker will loose to much coins on gas and forward fee, than `check_transaction` will loose on storage fee.

By the way, in each contract I check msg.value > constant. Constant should be greater 1 ton + epsilon. Even if contract fails with out of gas, bounced message will be generated. But I use `const int MIN_MSG_VALUE = 500 * 1000 * 1000; ;; 0,5 ton`. It was for testing on devnet. I forgot to return it to 1.5 ton.
Hey, good work with the bridge. Two areas need extra attention:

1. Not storing the previous validator set makes it impossible to verify transactions in the first key block in an epoch (which is signed by the previous epoch’s validators).

2. No handling for transition periods between validator sets. Without storing the next validator set, the current set could manipulate the next set.

What do you think?
macOS
Subtle Swallow Feb 6 at 22:44
Thank you for the questions.

1. It depends on what we call an epoch. The task hasn't defined it. I think the block signed by the previous epoch’s validators is the previous epoch's block.

2. I don't understand the question. Please give a couple of examples.
In PoS blockchains, an epoch refers to the time span during which a set of validators is responsible for signing blocks. In the TON blockchain, this is represented by utime_since and utime_until. Each epoch typically has two key blocks:

Starting key block: This is the first key block of an epoch, where the validator set transitions to next_validators. However, this block is still signed by the previous epoch’s validators.

Transitioning key block: This block is generated before the epoch ends. The validator set remains unchanged, but the next_validators set is defined for the upcoming epoch.

1. Can your code verify transactions in a starting key block? Since the validator set has already changed in the contract and "transactions in a new keyblock are still signed with the previous validator set", verification would require access to the previous validator set (or not checking the signatures at all and checking the seqno, since the block is already verified).
macOS
Implemented basic functionality with a few security issues: no max_main_validators logic, no signature deduplication, no global_id checks(minor), prev_key_block is substituted with set hash check (ok). Proper tx checker.

More info on issues: https://contest.com/docs/TrustlessBridgeChallengeAssessment
Subtle Swallow Feb 19 at 16:42
1) no signature deduplication
See comment above (`Subtle Swallow Feb 8 at 11:02`):
In `check_validator_signatures` I use a validator's pubkey as a hash map key so it's impossible to have more than one signature for each validator.

2) no global_id checks(minor)
I have such check. See lite_client.fc, line 122.

Pls, see the screenshots and check my code.
Nobody added any issues yet...