Litecoin learning center

Time Warp Attack

The time warp attack is based on a bug in Bitcoin and Litecoin (and their forks) where the difficulty calculation is off by one block. This flaw that affects all coins, especially ones with low network hash rates.

An attacker can repeatedly try to generate the last block of each retarget window, and use a fabricated timestamp of two hours into the future in order to make the time difference from the first block in the retarget window high, thus lowering the difficulty by 0.5%.Due to the bug, the bogus timestamp isn't used as the first block in the next retarget window, and therefore the two extra hours aren't being compensated for in the next difficulty calculation. Once the difficulty is low, the attacker can mine many fast coins, or in the case of a small chain, an attacker with 51% hash power could reduce the difficulty to 1 and mine a new fork from the genesis block.

This attack may not be as feasible any longer because the probability of repeatedly generating the last block once every two weeks at such high difficulties may be negligible.

Additional information is available from ArtForz: https://bitcointalk.org/index.php?topic=43692.msg521772#msg521772

Zeitgeist2 Attack

A fix in Litecoin's code has prevented one type of time warp attack, the Zeitgeist2 51% attack.The following changes were made to Litecoin Core to prevent the Zeitgeist2 attack:

1unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader *pblock, const Consensus::Params& params)
2{
3    // [...]
4
5    // Go back by what we want to be 14 days worth of blocks
6-    int nHeightFirst = pindexLast->nHeight - (params.DifficultyAdjustmentInterval()-1);
7-    assert(nHeightFirst >= 0);
8-    const CBlockIndex* pindexFirst = pindexLast->GetAncestor(nHeightFirst);
9+    // Litecoin: This fixes an issue where a 51% attack can change difficulty at will.
10+    // Go back the full period unless it's the first retarget after genesis. Code courtesy of Art Forz
11+    int blockstogoback = params.DifficultyAdjustmentInterval()-1;
12+    if ((pindexLast->nHeight+1) != params.DifficultyAdjustmentInterval())
13+        blockstogoback = params.DifficultyAdjustmentInterval();
14
15+    // Go back by what we want to be 14 days worth of blocks
16+    const CBlockIndex* pindexFirst = pindexLast;
17+    for (int i = 0; pindexFirst && i < blockstogoback; i++)
18+        pindexFirst = pindexFirst->pprev;
19
20}
21
22unsigned int CalculateNextWorkRequired(const CBlockIndex* pindexLast, int64_t nFirstBlockTime, const Consensus::Params& params)
23{
24    // Retarget
25-    const arith_uint256 bnPowLimit = UintToArith256(params.powLimit);
26    arith_uint256 bnNew;
27    arith_uint256 bnOld;
28    bnNew.SetCompact(pindexLast->nBits);
29+    bnOld = bnNew;
30+    // Litecoin: intermediate uint256 can overflow by 1 bit
31+    const arith_uint256 bnPowLimit = UintToArith256(params.powLimit);
32+    bool fShift = bnNew.bits() > bnPowLimit.bits() - 1;
33+    if (fShift)
34+        bnNew >>= 1;
35    bnNew *= nActualTimespan;
36    bnNew /= params.nPowTargetTimespan;
37+    if (fShift)
38+        bnNew <<= 1;
39}
Author:
Date Published:
← Back to learning center
Litecoin Learning Center
>

Time Warp Attack

The time warp attack is based on a bug in Bitcoin and Litecoin (and their forks) where the difficulty calculation is off by one block. This flaw that affects all coins, especially ones with low network hash rates.

An attacker can repeatedly try to generate the last block of each retarget window, and use a fabricated timestamp of two hours into the future in order to make the time difference from the first block in the retarget window high, thus lowering the difficulty by 0.5%.Due to the bug, the bogus timestamp isn't used as the first block in the next retarget window, and therefore the two extra hours aren't being compensated for in the next difficulty calculation. Once the difficulty is low, the attacker can mine many fast coins, or in the case of a small chain, an attacker with 51% hash power could reduce the difficulty to 1 and mine a new fork from the genesis block.

This attack may not be as feasible any longer because the probability of repeatedly generating the last block once every two weeks at such high difficulties may be negligible.

Additional information is available from ArtForz: https://bitcointalk.org/index.php?topic=43692.msg521772#msg521772

Zeitgeist2 Attack

A fix in Litecoin's code has prevented one type of time warp attack, the Zeitgeist2 51% attack.The following changes were made to Litecoin Core to prevent the Zeitgeist2 attack:

1unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader *pblock, const Consensus::Params& params)
2{
3    // [...]
4
5    // Go back by what we want to be 14 days worth of blocks
6-    int nHeightFirst = pindexLast->nHeight - (params.DifficultyAdjustmentInterval()-1);
7-    assert(nHeightFirst >= 0);
8-    const CBlockIndex* pindexFirst = pindexLast->GetAncestor(nHeightFirst);
9+    // Litecoin: This fixes an issue where a 51% attack can change difficulty at will.
10+    // Go back the full period unless it's the first retarget after genesis. Code courtesy of Art Forz
11+    int blockstogoback = params.DifficultyAdjustmentInterval()-1;
12+    if ((pindexLast->nHeight+1) != params.DifficultyAdjustmentInterval())
13+        blockstogoback = params.DifficultyAdjustmentInterval();
14
15+    // Go back by what we want to be 14 days worth of blocks
16+    const CBlockIndex* pindexFirst = pindexLast;
17+    for (int i = 0; pindexFirst && i < blockstogoback; i++)
18+        pindexFirst = pindexFirst->pprev;
19
20}
21
22unsigned int CalculateNextWorkRequired(const CBlockIndex* pindexLast, int64_t nFirstBlockTime, const Consensus::Params& params)
23{
24    // Retarget
25-    const arith_uint256 bnPowLimit = UintToArith256(params.powLimit);
26    arith_uint256 bnNew;
27    arith_uint256 bnOld;
28    bnNew.SetCompact(pindexLast->nBits);
29+    bnOld = bnNew;
30+    // Litecoin: intermediate uint256 can overflow by 1 bit
31+    const arith_uint256 bnPowLimit = UintToArith256(params.powLimit);
32+    bool fShift = bnNew.bits() > bnPowLimit.bits() - 1;
33+    if (fShift)
34+        bnNew >>= 1;
35    bnNew *= nActualTimespan;
36    bnNew /= params.nPowTargetTimespan;
37+    if (fShift)
38+        bnNew <<= 1;
39}
WRITTEN BY:
PUBLISHED ON:
Get involved

Donate

As a nonprofit organization, the Litecoin Foundation relies on community generosity!

Any and all donations are greatly appreciated, and will help further the development of Litecoin!

Newsletter

Our newsletter comes out monthly, with special giveaways, announcements on partnerships and development, and exclusive Litecoin news.

Sign up today and keep an eye on your inbox!

Thank you for signing up!
Please try again

Volunteer

If you’d like to use your expertise to promote, develop or grow Litecoin - or assist the Litecoin Foundation - we’d love to hear from you.

Simply fill in the form and we'll get back to you ASAP. Thank you in advance!

Copyright © 2024 Litecoin Foundation. | Privacy Policy