bitshares / bitshares/bitshares-core

Expired transactions with expiration time later than last block are possible to be included in a new block

Open
#356 3 comments 0 reactions 0 assignees View on GitHub
bug informative
Dominant language
C++
Stars
1.2k
Forks
660
Avg merge
8h 17m
Merged PRs (30d)
26

Description

The `expiration` field of transactions is checked in `_apply_transaction()` in `db_block.cpp` ([code](https://github.com/bitshares/bitshares-core/blob/bf4b80ece55f83524b111492480088dbb0ff9139/libraries/chain/db_block.cpp#L595-L599)):
```
fc::time_point_sec now = head_block_time();
FC_ASSERT( trx.expiration <= now + chain_parameters.maximum_time_until_expiration, "",
("trx.expiration",trx.expiration)("now",now)("max_til_exp",chain_parameters.maximum_time_until_expiration));
FC_ASSERT( now <= trx.expiration, "", ("now",now)("trx.exp",trx.expiration) );
```
`head_block_time()` is implemented in `db_getter.cpp` ([code](https://github.com/bitshares/bitshares-core/blob/bf4b80ece55f83524b111492480088dbb0ff9139/libraries/chain/db_getter.cpp#L60-L63)):
```
time_point_sec database::head_block_time()const
{
return get( dynamic_global_property_id_type() ).time;
}
```
The `time` field is updated in `update_global_dynamic_data()` in `db_update.cpp` ([code](https://github.com/bitshares/bitshares-core/blob/bf4b80ece55f83524b111492480088dbb0ff9139/libraries/chain/db_update.cpp#L81)):
```
void database::update_global_dynamic_data( const signed_block& b )
{
...
modify( _dgp, [&]( dynamic_global_property_object& dgp ){
...
dgp.time = b.timestamp;
...
```
But `_apply_transaction()` is called before `update_global_dynamic_data(next_block)` in `_apply_block()` ([code](https://github.com/bitshares/bitshares-core/blob/bf4b80ece55f83524b111492480088dbb0ff9139/libraries/chain/db_block.cpp#L504-L516)):
```
for( const auto& trx : next_block.transactions )
{
apply_transaction( trx, skip );
++_current_trx_in_block;
}

update_global_dynamic_data(next_block);
```

So theoretically if a transaction's `expiration` field is later than last block's timestamp, but earlier than the new block's timestamp, it can still be included in the new block and pass the check? Please let me know if I'm wrong.

Contributor guide

No contributing guide indexed for this repository

Research direction

Start by tracing _apply_block() and apply_transaction() in libraries/chain/db_block.cpp, then compare head_block_time() in db_getter.cpp with update_global_dynamic_data() in db_update.cpp. Confirm whether transaction validation uses the previous block timestamp and determine whether an expiration between the two timestamps can be accepted; done means the behavior is conclusively explained and any required correction is identified.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
blockchain
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.