Info

Download ZIP (37.1 KB)

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

26

Comments

I just noticed that by leaving all optimizations until the end, I overlooked optimizing the `check_sign` function in the `lite-client`. As a result, during each iteration, the function unnecessarily recreates the same data for signing the block.
You have not added any comments yet...
by rating

Issues

Implementation looks good overall. One thing:

- I don't think checking `new_seqno > seqno` is enough, because some set of validators could have a 2/3 majority in the current epoch, but not in a future one. I think checking given block's `prev_key_block_seqno` is required instead
1
Regal Scorpion Feb 8 at 13:18
I don't quite understand the issue. If the concern is that we might skip an intermediate key block and register a later one instead, this is not a problem given the system's design. We store only the latest key block, not a chain of blocks, and anyone can register new key blocks.
In the function you ignore blocks from current epoch that has seqno less than last known seqno
Regal Scorpion Feb 8 at 13:34
The contract stores the seqno of the epoch start and cannot receive a seqno of the current epoch that is lower than the stored one.
You don't check that transaction is presented block in tx checker (or lite-client).
You have `check_tx` but is not correct.
Regal Scorpion Feb 8 at 13:34
Could you clarify the issue in more detail?
RE: Regal Scorpion

Say lite client syncs up to epoch 1, which includes validator A with 70% weight.
Someone sends a block from epoch 2 with A's signature in check_block to lite client, lite client will reply that it's correct even if validator A only has 60% of weight in epoch 2.

Point being, lite client can't validate blocks from future epochs because it doesn't know what the validator distribution will be. So it needs to check whether the block is within the current epoch exactly. The `new_seqno > seqno` check would also allow blocks from future epochs
Regal Scorpion Feb 8 at 14:36
Your argument is valid. However, in practice, it does not introduce a new security risk.
If we assume that 2/3 of the validators in a given epoch can collude, then the system is already compromised, regardless of whether they attempt to validate an invalid block for the next epoch or their own. The key point is that such a scenario already breaks trust in the network, making the specific validation check for prev_key_block_seqno non-essential.
In other words, while skipping this check theoretically allows for an attack vector, it does not create an additional risk beyond the fundamental problem of assuming a 2/3 validator collusion, which is a critical failure in any case.
However, the issue is accepted.
Clarify on `Subtle Swallow Feb 8 at 13:21`
You proof that tx is in block. But you don't proof that it is a transaction. It can be fork of aug hashmap.
Regal Scorpion Feb 10 at 00:14
The concern about a "fork of aug hashmap" is incorrect. Cryptographically, it is impossible to construct a different transaction that produces the same hash as a fork of the augmented hashmap.
Reply on `Regal Scorpion Feb 10 at 00:14`
But you don't check that tx is `Transaction`.
https://github.com/ton-blockchain/ton/blob/master/crypto/block/block.tlb#L291-L297
It starts with `0111`, has `account_addr`, `lt`, etc.
Regal Scorpion Feb 10 at 00:22
The purpose of a hash is to serve as a cryptographic commitment to the data, allowing verification without checking every field explicitly.
> The purpose of a hash is to serve as a cryptographic commitment to the data, allowing verification without checking every field explicitly.

Yes, it's true. But attacker can take a fork from block and your contract will say that it's correct transaction. But it's not a transaction, it's a fork.
Regal Scorpion Feb 10 at 00:48
The check guarantees that the provided transaction hash exists in the verified block. Even if an attacker submits the hash of a forked augmented hashmap instead of a transaction, it gives them no advantage. Since referencing a non-transaction hash has no practical effect, this additional check does not add any real security benefit.
I intentionally skipped some checks to save gas.
Can you clarify what is going on here? What is the structure of the proof parameter? It seems that you check that hash of something inside proof corresponds to block hash, but then can force contract to skip checked field and pass to the next reference if has_shards=true.
Regal Scorpion Feb 14 at 09:12
The `proof` structure is described at the beginning of the `tx-checker.ts` file.
Implemented basic functionality with a few security issues: no main_validators logic, signature deduplication implemented but seems like missing one siganture causes inability to check all subsequent (if top-1 validator didn't sign, block won't be accepted), no global_id/prev_keyblock checks. "Hints"-based tx search (insecure). CHecking on proofs for tx_checker is quite complicated, seems like attempt of implementation of shard transaction checks introduce security issues.

More info on issues: https://contest.com/docs/TrustlessBridgeChallengeAssessment
Regal Scorpion Feb 19 at 16:56
Thanks for the review!
Regarding this concern:
"If the top-1 validator didn't sign, the block won't be accepted."

This is not actually the case. The logic does not depend on any specific validator signing. Instead, it iterates over all validators from the config and accumulates the signed weights.
If a high-weight validator does not sign, a "false" flag is set for them, and in the contract, their weight is considered zero. This ensures that missing a high-weight validator does not prevфent the block from being accepted, as long as enough other validators sign.

As for:
"Checking on proofs for tx_checker is quite complicated, seems like attempt of implementation of shard transaction checks introduce security issues."

Yes, this is indeed an implementation of shard transaction checks.
>top-1 validator didn't sign
Indeed: the fact that absent signature can be encoded and processed correctly nullify this part of the issue. A little bit more expensive than necessary, but works. Objection accepted.
Nobody added any issues yet...