Timedrift exploit on PoS coins to increase minting probability


#9

[quote=“Thireus, post:7, topic:3338”][quote=“presstab, post:6, topic:3338”]Hey guys, cool to see you already linked to my findings. I have a full article released about it here: http://bitcoinist.net/interview-presstab-pos-vulnerabilities/

There is no myth about this problem, anyone can hash with about a 12,000% advantage on the current PPC code and be completely within the bounds of the protocol. I think that if PPC were wise, it would instead of saying “this is not a problem”, just go ahead and change the timedrift variable. It is not hard.

Also keep in mind that the most significant risk about this problem, in my opinion, is the impact on difficulty. If everyone runs this code, block target will be significantly overshot.[/quote]

Hi presstab,

Thank you for posting here. Could you share with us your thoughts about which timedrift value we should use, and what would be the consequences (apart from preventing this attack).

Cheers.[/quote]

We changed HyperStake from 15 minutes timedrift to 60 seconds. Giving a binary to all of our peers that allowed 5 minute hashdrift created a major decrease in difficulty and overshooting targets by more than double. 60 seconds seems natural because A) that is what the standard ppc client is hashing into the future anyways, so it shouldn’t change much of how the network is operating B) there is reason to have some drift allowance, slow internet connections, etc.

BLK and some other coins are using 15 second. Not sure how that is going, but I would assume high orphan rate. Even our new 60 second drift is creating a bit higher orphan rate, but nothing absurd.


#10

[quote=“presstab, post:9, topic:3338”][quote=“Thireus, post:7, topic:3338”][quote=“presstab, post:6, topic:3338”]Hey guys, cool to see you already linked to my findings. I have a full article released about it here: http://bitcoinist.net/interview-presstab-pos-vulnerabilities/

There is no myth about this problem, anyone can hash with about a 12,000% advantage on the current PPC code and be completely within the bounds of the protocol. I think that if PPC were wise, it would instead of saying “this is not a problem”, just go ahead and change the timedrift variable. It is not hard.

Also keep in mind that the most significant risk about this problem, in my opinion, is the impact on difficulty. If everyone runs this code, block target will be significantly overshot.[/quote]

Hi presstab,

Thank you for posting here. Could you share with us your thoughts about which timedrift value we should use, and what would be the consequences (apart from preventing this attack).

Cheers.[/quote]

We changed HyperStake from 15 minutes timedrift to 60 seconds. Giving a binary to all of our peers that allowed 5 minute hashdrift created a major decrease in difficulty and overshooting targets by more than double. 60 seconds seems natural because A) that is what the standard ppc client is hashing into the future anyways, so it shouldn’t change much of how the network is operating B) there is reason to have some drift allowance, slow internet connections, etc.

BLK and some other coins are using 15 second. Not sure how that is going, but I would assume high orphan rate. Even our new 60 second drift is creating a bit higher orphan rate, but nothing absurd.[/quote]

Thank you presstab, I’ve just opened an issue on ppcoin’s github. Hopefully this will be fixed in the next version release: https://github.com/ppcoin/ppcoin/issues/82


#11

Changing the nMaxClockDrift variable requires additional changes. Previous blocks that were accepted within this window would be rejected if they are outside the newly chosen window.

What would you suggest presstab to continue accepting the previous blocks? Manually set a timestamp to state before this date nMaxClockDrift = 2h, after this date nMaxClockDrift = 60sec?


#12

How is sigmike’s answer invalid?

Since the network has a tolerance of two hours of time stamp error, does it mean one can try 14400 different time stamps per second?[/quote]

Yes. There are other limits involved but you can try more timestamps per second. The client already tries some previous timestamps if you missed them.

But if you try the next 14400 timestamps at time t, then at time t+1 you’ll try 14399 timestamps you’ve already tried, and only try 1 new. So you still try only 1 new timestamp per second.

If you do that it may still be a little easier to find a block if the difficulty changes a lot (because you’ll try more timestamps when the difficulty is low). But it’s probably not significant. And you wouldn’t get more reward, you’d only a part of it earlier.[/quote]


#13

[quote=“Thireus, post:11, topic:3338”]Changing the nMaxClockDrift variable requires additional changes. Previous blocks that were accepted within this window would be rejected if they are outside the newly chosen window.

What would you suggest presstab to continue accepting the previous blocks? Manually set a timestamp to state before this date nMaxClockDrift = 2h, after this date nMaxClockDrift = 60sec?[/quote]

You just say if timestamp is less than x use drift 1 else drift 2.


#14

[quote=“emeth, post:12, topic:3338”]How is sigmike’s answer invalid?

Since the network has a tolerance of two hours of time stamp error, does it mean one can try 14400 different time stamps per second?[/quote]

Yes. There are other limits involved but you can try more timestamps per second. The client already tries some previous timestamps if you missed them.

But if you try the next 14400 timestamps at time t, then at time t+1 you’ll try 14399 timestamps you’ve already tried, and only try 1 new. So you still try only 1 new timestamp per second.

If you do that it may still be a little easier to find a block if the difficulty changes a lot (because you’ll try more timestamps when the difficulty is low). But it’s probably not significant. And you wouldn’t get more reward, you’d only a part of it earlier.[/quote][/quote]

Its not invalid, it just doesn’t really address any of the issues.

The biggest issue is difficulty adjustment that happens from submitting blocks in the future, and he seems to not consider this at all.

I have the power to stake into the future, lower the difficulty significantly, and have thousands of more chances to stake at the given moment in time than you do. Given enough stakes coming in with this code, it will make it much easier to perform a double spend or another attack on the chain.

All it really takes is for someone like me to create a wallet with the code, release it and say “hey everyone use this and you will stake much faster”, and the network gets really screwed up once enough jump on the new wallet.


#15

Peercoin’s minting maybe isn’t optimal because it’s built upon PoW mining code and previous protocol, I’ll make a PR and we’ll discuss it. New designs introduce new holes so it’s safer to base on tested code and optimize it later.
—edit—
@ http://bitcoinist.net/interview-presstab-pos-vulnerabilities/

Each second that goes by, the code will then hash the same 59 hashes that it did one second ago, adding one new hash to the end that reflects the time changing. This becomes a burden on the CPU, and there is no reason to hash the same exact hash over and over.
That's false. ---!edit---

Author of article mixes coins w/ different block interval targets, diff adjusting algos and other PoS parameters(2h drift, 10min target != 2h drift, 1min target) so it’s hard to say if his study and conclusions match our network, ofc it worths exploring.


#16

Looking at function CBlock* CreateNewBlock once more, if the line
if (nSearchTime > nLastCoinStakeSearchTime)
really means that newer block has to be later than the previous, it could mean that tweaked nodes may prevent another blocks from happening.

example: lets say you know (with the help of findstakejs) that one output of mine wil be tomorrow at 11:02 AM at a min difficulty of 16.1

Unless the diff is higher than 16.1 tomorrow I will mint that stake, no matter how many ohers have tweaked nodes/minted or not.
That is because no hashes of previous blocks are needed to calculate my stake.
The idea that a tweaked node may effect the diff dropping only assures my future mint.
That said, if a tweaked node were to be able to stake at 11:15 while the actual time is 10:03, will this prevent me from getting my stake accepted by the network by the time my stake is found?


#17

[member=30004]thehuntergames[/member]
Example: you’ll be able to mint

// Check timestamp against prev if (GetBlockTime() <= pindexPrev->GetMedianTimePast() || GetBlockTime() + nMaxClockDrift < pindexPrev->GetBlockTime()) return error("AcceptBlock() : block's timestamp is too early");

Your stake(/block) time have to be higher than median of past 11 blocks.


#18

thx
I’ll consider the myth busted. Maybe the theory was based on NXT code? dunno, it has no hold on the inner workinks of ppc.

However, I do think someone, preferably a copywriter, should rewrite that chapter what pillow initially wrote. I dont find it clear and concise IMHO.


#19

Wait…what? What do you mean the myth is busted? The myth is no longer a myth but a fact!


#20

The notion that it is 11,900% more likely to hit a hash is BS.

Actually the time when you can stake are predefined. Just play with findstakejs and see for yourself. It is just up to you to start up your wallet when that opportunaty comes along.

It the diff drops just because of a number of tweaked nodes only helps to find more stakes.

There is a post that details ‘How findstake is determined’ and the take away is nothing matters, as long as people mint on time. It does not matter that more or less stakes are found by others.
As it does not need hashes from the previous block.
It is like playing blackjack iso poker, it is between you and the dealer. How other players play wont effect the result


#21

[quote=“kac-, post:15, topic:3338”]Peercoin’s minting maybe isn’t optimal because it’s built upon PoW mining code and previous protocol, I’ll make a PR and we’ll discuss it. New designs introduce new holes so it’s safer to base on tested code and optimize it later.
—edit—
@ http://bitcoinist.net/interview-presstab-pos-vulnerabilities/

Each second that goes by, the code will then hash the same 59 hashes that it did one second ago, adding one new hash to the end that reflects the time changing. This becomes a burden on the CPU, and there is no reason to hash the same exact hash over and over.
That's false. ---!edit---

Author of article mixes coins w/ different block interval targets, diff adjusting algos and other PoS parameters(2h drift, 10min target != 2h drift, 1min target) so it’s hard to say if his study and conclusions match our network, ofc it worths exploring.[/quote]

True that a ten minute block target is not quite as bad. But this is not a reason to excuse it as a myth… Plain and simple, give me enough weight and your difficulty will be ruined. Maybe PPC’s days of being aggressive on security are over? I am not sure. Good luck to you guys.


#22

Quote please.


#23

Quote please.[/quote]


#24

Maybe thehuntergames was talking about this [quote=“thehuntergames, post:16, topic:3338”]Looking at function CBlock* CreateNewBlock once more, if the line
if (nSearchTime > nLastCoinStakeSearchTime)
really means that newer block has to be later than the previous, it could mean that tweaked nodes may prevent another blocks from happening.

example: lets say you know (with the help of findstakejs) that one output of mine wil be tomorrow at 11:02 AM at a min difficulty of 16.1

Unless the diff is higher than 16.1 tomorrow I will mint that stake, no matter how many ohers have tweaked nodes/minted or not.
That is because no hashes of previous blocks are needed to calculate my stake.
The idea that a tweaked node may effect the diff dropping only assures my future mint.
That said, if a tweaked node were to be able to stake at 11:15 while the actual time is 10:03, will this prevent me from getting my stake accepted by the network by the time my stake is found?[/quote]

I said that it worths exploring, simulation maybe.
[member=30004]thehuntergames[/member] have you ported diff calculation code to JS?


Edit:
Valid scenario is: everyone is minting +2h ahead, in case of fork there is high probability that owner of orphaned block won’t be able to mint once again on a main chain.
That would allow an attacker to exclude some minters = keep diff lower. Condition: lot of minters use modified „future-mint” client.


#25

[quote=“thehuntergames, post:16, topic:3338”]Looking at function CBlock* CreateNewBlock once more, if the line
if (nSearchTime > nLastCoinStakeSearchTime)
really means that newer block has to be later than the previous, it could mean that tweaked nodes may prevent another blocks from happening.

example: lets say you know (with the help of findstakejs) that one output of mine wil be tomorrow at 11:02 AM at a min difficulty of 16.1

Unless the diff is higher than 16.1 tomorrow I will mint that stake, no matter how many ohers have tweaked nodes/minted or not.
That is because no hashes of previous blocks are needed to calculate my stake.
The idea that a tweaked node may effect the diff dropping only assures my future mint.
That said, if a tweaked node were to be able to stake at 11:15 while the actual time is 10:03, will this prevent me from getting my stake accepted by the network by the time my stake is found?[/quote]

I don’t think you are correct, feel free to correct me if I am wrong with my reading of the code.

CreateNewBlock() is triggered by BitcoinMiner().
Initializes with your adjusted time:

static int64 nLastCoinStakeSearchTime = GetAdjustedTime();

nSearchTime is initialized as your txtime for this new block

int64 nSearchTime = txCoinStake.nTime;

You then use checkKernalCoinStake() to find a successful PoS hash
and nLastCoinStakeSearchTime is set to your nSearchTime

nLastCoinStakeSearchTime = nSearchTime;

You continue through the rest of the createblock process because you have successfully produced a stake hash that meets the target. You then exit createblock with your new block. All variables are reinitialized upon restarting the createblock process.

A) I don’t see anywhere that nLastCoinStakeSearchTime is assigned to your submitted tx time, so if you submitted a block way into the future, why would it have that value stored somewhere?
B) The function is reset upon exit
C) This is node specific code, not something that is sent to peers

Am I missing something in my reading of the code, it does get complicated quick, I will be the first to admit that.

I know that it is not uncommon at all for PoS blocks to come in out of chronological order. PPC would be less common because of the larger target spacing, but that doesn’t mean the code forbids it.


#26

Almost.

static int64 nLastCoinStakeSearchTime = GetAdjustedTime();

static modifier makes this variable initialized only once, it’s like:

if( nLastCoinStakeSearchTime == 0 ){ nLastCoinStakeSearchTime = GetAdjustedTime(); }

—Edit—
Yep, it reffers to local node minting only, it counters your note about redundant hashing.


#27

Hmm alright so that would mean that it also survives the exit of the function too?

Also, this would only be about redundant hashing, not the ability to produce a stake at time value +2hours and then stake again at time value +5 minutes correct?


#28
Hmm alright so that would mean that it also survives the exit of the function too?
Yep, it's like declared outside of function but visible only in enclosing func.
Also, this would only be about redundant hashing, not the ability to produce a stake at time value +2hours and then stake again at time value +5 minutes correct?
+2h yes +5min idk, how you came to this?