Nuke adjusted time (attempt 2) (p2p, consensus)

https://github.com/bitcoin/bitcoin/pull/28956

Host: stickies-v  -  PR author: dergoegge

The PR branch HEAD was 1d226ae1f984c5c808f5c24c431b959cdefa692e at the time of this review club meeting.

Notes

  • Bitcoin relies on the concept of time for operations such as the difficulty adjustment and transaction- or script-level timelocks. Since time is relative and clocks are notoriously difficult to keep synchronized, it is impossible to define a source of truth that does not depend on synchronization and authorities such as NTP servers. In a decentralized system, we must accept that nodes can have a different but equally valid view of the current time.

  • The Bitcoin network comes to consensus on time by requiring miners to commit to a timestamp in the block header. To prevent miners from being able to use excessively deviating timestamps in their blocks, nodes verify that the timestamp is later than the Median Time Past (calculated on the previous 11 blocks), and earlier than 2 hours from the current time.

  • Prior to this PR, the current time was calculated based on the network-adjusted time. When connecting to a peer, the peer’s current time is compared to the system’s current time, and the time difference is stored. The network-adjusted time is then calculated by adding the median of all peers’ offsets to the system’s current time, unless it exceeds the -maxtimeadjustment value in which case a warning is emitted.

  • With this PR, the upper bound of the validity of a block header’s timestamp is no longer calculated based on the network-adjusted time, but on the unadjusted system’s current time. The network-adjusted time is still calculated and used to warn users of a potential clock misconfiguration.

  • Note: the description in timedata.cpp mentions that “the condition to update nTimeOffset includes checking whether the number of elements in vTimeOffsets is odd, which will never happen after there are 200 elements.”. This comment has become outdated since #6545, which made the maximum number of elements explicit in an earlier check.

Questions

Concept

  1. Did you review the PR? Concept ACK, approach ACK, tested ACK, or NACK? What was your review approach?

  2. Is it necessary for block headers to have a timestamp? If so, why?

  3. What is the difference between Median Time Past (MTP) and network-adjusted time? Which of these are relevant to the PR?

  4. Why are limits enforced on how far “off” a block header’s timestamp is allowed to be from a node’s internal clock? And since we don’t require exact agreement on time, can these limits be made more strict?

  5. Prior to this PR, why would an attacker try to manipulate a node’s network-adjusted time?

  6. Prior to this PR, how could an attacker try to manipulate a node’s network-adjusted time? Which network message(s) would they use? Hint: network messages are processed in net_processing.cpp

  7. Does this PR remove any attack vectors? Does it introduce new ones?

  8. Does this PR change consensus behaviour? If so, is this a soft fork, a hard fork, or neither? Why?

  9. After this PR, does it still matter for a non-mining node to have its system time (roughly) agree with that of the network? Why (not)?

Code

  1. Which operations were relying on network-adjusted time prior to this PR?

  2. Does this PR introduce any difference in how and when it warns for a clock that appears out-of-sync with the network?

  3. TimeOffsets has a size of 199, but CMedianFilter was initialized with a size of 200. What explains this difference?

  4. Which of the values {0, 5, -2, 50s, 70m} are valid inputs for -maxtimeadjustment?

  5. CMedianFilter internally used two std::vectors, whereas TimeOffsets uses a single std::array. What do you see as the trade-offs between these approaches?

  6. Commit 0fb8cbb removes a comment about not checking again for the 2-hours-in-the-future rule. Can and/or should this check now be introduced here?

Meeting Log

Meeting 1

  117:00 <stickies-v> #startmeeting
  217:00 <dergoegge> hi
  317:00 <stickies-v> hi everyone, welcome to the first review club of 2024!
  417:00 <effexzi> Hey every1
  517:00 <vmammal> hi
  617:00 <monlovesmango> hey
  717:00 <hernanmarino> hi everyone
  817:00 <alfonsoromanz> hey everyone
  917:00 <Ayelen> Hi
 1017:01 <michaelfolkson> hi
 1117:01 <stickies-v> Today we're looking at #28956, authored by dergoegge. The notes and questions are available on https://bitcoincore.reviews/28956
 1217:01 <kevkevin> hi
 1317:01 <pablomartin> hello
 1417:01 <glozow> hi
 1517:01 <lightlike> Hi
 1617:01 <stickies-v> anyone joining us for the first time today? even if you're just lurking, feel free to say hi!
 1717:02 <alfonsoromanz> this is my first time today :)
 1817:02 <Ayelen> first time today
 1917:02 <stickies-v> nice, welcome alfonsoromanz !
 2017:02 <stickies-v> and Ayelen. Feel free to just lurk or chime in whenever you want to
 2117:03 <Ayelen> thanks!
 2217:03 <alfonsoromanz> sounds good
 2317:03 <stickies-v> who got the chance to review the PR or read the notes? (y/n)
 2417:03 <hernanmarino> y
 2517:03 <alfonsoromanz> y
 2617:03 <dergoegge> y
 2717:03 <TheCharlatan> y
 2817:04 <Ayelen> y
 2917:04 <henmeh> y
 3017:04 <TheCharlatan> hi
 3117:04 <stickies-v> for those of you who were able to review, would you give it a Concept ACK, Approach ACK, Tested ACK, or NACK? what was your review approach?
 3217:04 <TheCharlatan> Concept ACK
 3317:04 <hernanmarino> Concept ACK
 3417:05 <pablomartin> havent reviewed it yet, but read notes
 3517:05 <stickies-v> nice!
 3617:06 <stickies-v> so today, we'll be focusing on the conceptual questions, and tomorrow we'll dive more into the code
 3717:06 <stickies-v> given that consensus is touched, the conceptual understanding is pretty critical for this PR, probably more so than the actual code
 3817:07 <stickies-v> let's get started with the questions:
 3917:07 <stickies-v> 2. Is it necessary for block headers to have a timestamp? If so, why?
 4017:07 <michaelfolkson> Not convinced on the Concept ACK personally but hope to be convinced :)
 4117:07 <alfonsoromanz> Yes so your node can make sure it’s in sync with the network
 4217:07 <monlovesmango> yes, for difficulty adjustment
 4317:07 <stickies-v> alfonsoromanz: what do you mean with "in sync"?
 4417:08 <stickies-v> or rather, why is it important?
 4517:08 <alfonsoromanz> that is on the right chain
 4617:08 <Guest60> hi
 4717:08 <stickies-v> the right chain is identified by the most cumulated proof of work, we don't really use timestamps for that
 4817:09 <stickies-v> monlovesmango: yes! that's one of the use cases. but there are more!
 4917:09 <pablomartin> seq order, difficulty adjustment, consensus mechanism, preventing timestime manipulation, human-readable information
 5017:10 <sr_gi> Hi! Sorry I'm late
 5117:10 <stickies-v> pablomartin: wdym with seq order and preventing timestime manipulation?
 5217:10 <monlovesmango> block validation too right?
 5317:10 <vmammal> hi sr_gi
 5417:10 <monlovesmango> which is what this pr touches
 5517:10 <stickies-v> no worries sr_gi, we're async anyway so feel free to continue discussing questions anytime - even if we've moved on to something else
 5617:11 <stickies-v> monlovesmango: well yes this PR affects how a block header's timestamps affects its validity, but if it didn't have the timestamp to begin with we wouldn't have to validate it :D
 5717:12 <pablomartin> seq order: blocks should be in chronologial order... preventing timestamp manipulation: helps prevent miners from manipulating the block creation process, miners must set the timestamp within certain limits
 5817:12 <stickies-v> blocks already point to the previous block header so that shouldn't really affect block order i think
 5917:12 <pablomartin> true
 6017:13 <vmammal> also the timestamp is needed to evaluate timelocked transactions, no?
 6117:13 <stickies-v> and re timestamp manipulation: that also doesn't really explain why we need the timestamp, just how it can be manipulated
 6217:13 <sr_gi> Isn't it necessary to compute the diff adjustment?
 6317:13 <stickies-v> vmammal: yes exactly! we need consensus on a specific time in order to validate timelocks
 6417:14 <stickies-v> sr_gi: indeed it is
 6517:14 <hernanmarino> sr_gi +1
 6617:14 <stickies-v> difficulty adjustment and timelocks are the two reasons I could think of, but maybe there are more?
 6717:14 <stickies-v> 3. What is the difference between Median Time Past (MTP) and network-adjusted time? Which of these are relevant to the PR?
 6817:14 <sr_gi> Our only sense of how long blocks take to get mined is based on the block timestamp, so in order to re-adjust we need to know how long it took (sorry if it was pointed out, I'm missing the chat log :'))
 6917:15 <stickies-v> nw, monlovesmango already mentioned the difficulty adjustment but thanks for that extra context đź‘Ť
 7017:16 <monlovesmango> mtp is calculated with past block timestamps whereas network-adjusted time is calculated based on first 199 outgoing peers' median time
 7117:16 <alfonsoromanz> MTP is the median time of last 11 blocks and network adjusted time is a time that is calculated by adding the median of the offsets between current node time and a sample of 200 peers, to try to get nodes closer to each other in terms of clock synchronization. For this PR only network adjusted time is relevant.
 7217:16 <monlovesmango> network adjusted is relevant here
 7317:17 <stickies-v> correct, monlovesmango and alfonsoromanz (although its based on 199 peers instead of 200, but we'll get to that in a bit)
 7417:17 <stickies-v> now, conceptually, there's another big distinction between them both
 7517:17 <monlovesmango> hehe yeah didn't quite follow that :)
 7617:18 <stickies-v> MTP is uniquely defined for all network participants that are on the same chain (i.e. there's consensus on time), whereas they can (and generally do) have a different network-adjusted time
 7717:18 <stickies-v> so, why don't we just use MTP for everything and scrap network-adjusted time?
 7817:19 <sr_gi> MTP is used as the lower bound for the timestamps of the subsequent block, whereas the network-adjusted time is our view of time corrected by the view of our peers (at least before this PR)
 7917:20 <monlovesmango> bc MTP cant be calculated for future time threshold
 8017:20 <stickies-v> monlovesmango: exactly!
 8117:20 <lightlike> a rule like "prevent a block >2 hours in the future" would not be possible with MTP
 8217:21 <stickies-v> 4. Why are limits enforced on how far "off" a block header's timestamp is allowed to be from a node's internal clock? And since we don't require exact agreement on time, can these limits be made more strict?
 8317:22 <sr_gi> The restrictions are in place to prevent tampering with the difficulty adjustments. If timestamps are to far off the future, when computing the next difficulty it would look like blocks took longer to be mined, wrongly correcting the difficulty down, the same applies, in the opposite way, if timestamps are too far into the past. These limits could
 8417:22 <sr_gi> be made more strict, given we are giving some room for discrepancies (maxtimeadjustment) but it we made them too strict valid blocks could be rejected, creating a consensus issue.
 8517:22 <monlovesmango> if timestamp is too far off it could be used to manipulate difficulty adjustment or time locks?
 8617:24 <stickies-v> sr_gi: monlovesmango both correct! this class of attacks is called timewarping attacks, if anyone wants to research more
 8717:24 <hernanmarino> exactly, to prevent miners to manipulate difficulty adjustments
 8817:25 <stickies-v> we don't need the time to be exactly correct, it's mostly important that it keeps moving in the right direction and that it keeps moving at the same pace as the wall clock on average
 8917:25 <stickies-v> 5. Prior to this PR, why would an attacker try to manipulate a node's network-adjusted time?
 9017:26 <michaelfolkson> If it is a node run by a miner to get its mined blocks rejected?
 9117:26 <monlovesmango> the only thing I could think of was to convince a node that a valid block is invalid and then broadcast a fake block to the node (that would be valid to the node)
 9217:27 <stickies-v> michaelfolkson: yep that's one reason!
 9317:27 <lightlike> or a mining node might not accept a valid new block and keep wasting hash power an old tip.
 9417:28 <monlovesmango> oh interesting lightlike
 9517:28 <sr_gi> Even to make a timely transaction with a time-lock to be rejected from a block in where it could potentially have been included
 9617:28 <michaelfolkson> And then there's the time dilation attacks on Lightning Antoine was discussing in a comment https://github.com/bitcoin/bitcoin/pull/25908#pullrequestreview-1127411015
 9717:29 <stickies-v> monlovesmango: yes! broadcasting a fake block would require a lot of hashpower of course, but forking nodes off the valid chain is possible like that
 9817:29 <stickies-v> lightlike: hadn't thought of that, you're right!
 9917:32 <stickies-v> sr_gi ooh and for timelocks with short windows that could actually be pulled off quite stealthily perhaps
10017:32 <stickies-v> 6. Prior to this PR, how could an attacker try to manipulate a node's network-adjusted time? Which network message(s) would they use? *Hint: network messages are processed in `net_processing.cpp`*
10117:32 <lightlike> if I rejected a block because it's too much in the future (>2h), and then some time passes and it's now valid, will my node accept it a bit later? Or will it be remembered as being invalid indefinitely?
10217:33 <michaelfolkson> I find it very difficult to assess the Concept ACK on this. As I think you say in a comment stickies-v it is making some esoteric attacks harder to pull off whilst potentially making some other esoteric attacks easier to pull off
10317:33 <stickies-v> lightlike: i think invalid blocks are never re-validated?
10417:34 <michaelfolkson> So you have to essentially assess whether you're more worried about an attacker controlling your local time or an attacker controlling all your peers
10517:34 <hernanmarino> lightlike: i think the problem is with eventual forks in the chain in that situation
10617:35 <stickies-v> michaelfolkson: yes, that is the main question to be answered for this PR imo
10717:35 <monlovesmango> michaelfolkson: i agree. in my gut it feels much easier to attack an individual with malware (to change system time) and little recourse for correction than to orchestrate being one of the first outgoing peers
10817:36 <dergoegge> adjusted time does not fully protect against NTP based attacks
10917:36 <lightlike> stickies-v: then how do I recover if my time is really wrong (>2h) for some reason, and I rejected a valid block, and now I fixed my time and wanna get back to the right chain?
11017:37 <monlovesmango> lightlike: i would imagine just like you sync a node, request the new blocks from peers
11117:38 <dergoegge> it's just extra complexity that doesn't really achieve anything imo
11217:38 <michaelfolkson> And then there's also the weighing up of dangers of forking yourself off the network versus contagion with forking peers off the network? (for admittedly esoteric attacks)
11317:38 <monlovesmango> dergoegge: correct, adjusted time doesn't protect against NTP based attacks. just think this attack is much harder to pull off than a targeted malware attack. but really don't know.
11417:38 <hernanmarino> Also NTP is not so difficult to attack, assuming you are using NTP
11517:39 <stickies-v> lightlike: that is a good point, and i see now that we have a `BlockValidationResult::BLOCK_TIME_FUTURE` so probably those blocks can be re-evaluated?
11617:39 <stickies-v> i can't immediately find it in the code tho
11717:40 <monlovesmango> but then I also think malware attack is already possible so are we really increasing the attack vector? myabe not
11817:40 <michaelfolkson> It is hard. I don't feel I understand the trade-offs well enough to assess the Concept ACK. I get the fact it is cleaner from a consensus code perspective post this PR but also not sure how much of a "big win" that really is
11917:41 <dergoegge> deleting 100s of lines of code that don't achieve what they claim seems like a good win to me
12017:42 <stickies-v> if a user knows how to safely manage their system clock, they are now vulnerable to one less attack
12117:42 <monlovesmango> but how many users really know how to do this?
12217:42 <monlovesmango> realistically i say less than 1%
12317:43 <monlovesmango> if we want non technical folks to run a node, this probably would be a hindrance, but only in cases where system time is off which is very rare)
12417:44 <michaelfolkson> dergoegge: With no trade-offs to consider and it not being consensus agreed that would be a good win. I just don't know personally
12517:44 <lightlike> re: question 6: An attacker would need to send us multiple version messages with manipulated timestamps. They would need us to make >50% of outbound connections to nodes controlled to them, which is hopefullly hard (but much easier than completely eclipsing the node).
12617:45 <stickies-v> lightlike yes, beautiful answer!
12717:45 <stickies-v> and the last bit is really important - does anyone know why that is much easier than eclipsing a node?
12817:47 <vmammal> if we have one honest peer, we're ok
12917:47 <vmammal> in theory
13017:47 <lightlike> also, an attacker would need to do this in the first couple hours after the victim's node has started, because after 199 sample cutoff.
13117:48 <stickies-v> yeah indeed vmammal, we always assume that we just need one honest peer to be fine - this doesn't hold for network-adjusted time
13217:50 <monlovesmango> so eclipsing attack is harder simply bc it only needs one honest peer to fail?
13317:50 <hernanmarino> in network-adjusted-time , one honest node is not enough because all nodes contribute to your computation of time
13417:51 <vmammal> hernanmarino ah, ok
13517:51 <stickies-v> hernanmarino: not really all of them, but because we're looking at the median you just need >50% malicious peers
13617:51 <hernanmarino> an even one dishonest node can alter your computation
13717:51 <hernanmarino> yes
13817:51 <stickies-v> so, no, one dishonest node cannot alter your computation
13917:52 <hernanmarino> but 51% is easier than 100% :)
14017:52 <hernanmarino> stickies-v: ok, agree
14117:52 <stickies-v> 8. Does this PR change consensus behaviour? If so, is this a soft fork, a hard fork, or neither? Why?
14217:53 <sr_gi> I think one relevant detail is that we only take one sample per peer, given that happens during the handshake (i.e. exchange of version messages), hence why a single peer cannot affect your computation
14317:54 <monlovesmango> yes I think it does change consensus..? soft fork?
14417:54 <michaelfolkson> It is one of those where technically it is a hard fork right? But in reality we're dealing with highly unlikely esoteric attacks and code cleanup
14517:55 <michaelfolkson> Relaxing a check?
14617:55 <sr_gi> I think it does not change consensus behavior but it can lead to consensus discrepancies, e.g a chain split due to what blocks are valid wrt time
14717:56 <monlovesmango> sr_gi: I think the nature of a median calculation means having <50% malicious peers should not affect your calculation
14817:56 <michaelfolkson> You expect it to not change consensus behavior and you're extremely confident it won't. But theoretically it could
14917:56 <TheCharlatan> +1 sr_gi
15017:56 <hernanmarino> michaelfolkson: totally agree with you
15117:57 <dergoegge> michaelfolkson: how could it?
15217:57 <sr_gi> monlovesmango you're right, but it only applies back to the amount of distinct peers because we sample on handshake. If you happen to do so on any other message that can be sent without disconnecting a single peer may affect multiple samples
15317:58 <michaelfolkson> dergoegge: Theoretically it is possible that you reject a block after this PR that you would have accepted before this PR? Emphasize "theoretically"
15417:59 <stickies-v> would adding better eclipse protection to Bitcoi Core constitute a hard fork?
15517:59 <stickies-v> mm no that's a bad example
15617:59 <monlovesmango> wouldn't this change also make bitcoin consensus more reliant on time servers?
15718:00 <monlovesmango> which could open up regional level attacks? this assumes that ppl are willing to manipulate time to mess with bitcoin
15818:01 <sr_gi> michaelfolkson I think that's a bit unfair. The root of why would you reject a block (both after and before this PR) is because your view of time deviates from "the network's", that can be achieved either by peers messing with your corrected time, or by your NTP server messing with you
15918:01 <sr_gi> So in both cases you would reject a somewhat valid block
16018:02 <dergoegge> sr_gi: +1
16118:02 <monlovesmango> "peers messing with your corrected time, or by your NTP server messing with you" agree, but imo NTP server messing with you seems easier to orchestrate
16218:02 <hernanmarino> sr_gi: that's interesting, chain splits could be occurring right now, without this PR
16318:03 <sipa> i happen to have just written an answer to a somewhat related question on bitcoin SE: https://bitcoin.stackexchange.com/questions/121247/how-exactly-is-the-timestamp-calculated-for-the-2h-acceptance-rule-and-do-i-hav/121251
16418:03 <sr_gi> I think the matter really boils down to how likely is is that after the change non-adjusted and adjusted clients may conflict, and that's a fair concern
16518:04 <hernanmarino> yes
16618:04 <sipa> i think it's important to realize that adjusted time rejection of a block isn't a permanent rejection
16718:04 <sr_gi> monlovesmango but that's something that can still happen currently
16818:04 <lightlike> I think it's important to note that adjusted time can only change time by a max of 70 minutes, which is smaller than the 120 minutes block rule. So I think that any meaningful attack would require the attacker to be a miner, that would date its own block almost 2 hours into the future, and then adjust the victim's time into the past.
16918:04 <sipa> which is why it's not really a consensus rule, just a network acceptance rule
17018:05 <monlovesmango> sr_gi: yes, but currently ntp server messing with you will not throw you out of consensus right?
17118:06 <michaelfolkson> The chain split risk is really the important question versus whether this is theoretically a hard fork or not. If the chain split risk reduces or is unimpacted then we're happy. And we're in the realm of edge cases anyway
17218:07 <stickies-v> i didn't want to interrupt the ongoing conversation but as we've gone quite a bit over time already i'll wrap up the meeting here
17318:07 <monlovesmango> thanks for hosting stickies-v!!
17418:07 <stickies-v> the lines between consensus, network and policy aren't always as clear!
17518:07 <sr_gi> I will I think, if you're far off, you'll adjust the time up to a certain extend, but not beyond `maxtimeadjustment`, but blocks times will still be off for you, so you won't accept them. That's my intuition at least, but take it with a grain of salt
17618:07 <lightlike> thank you stickies-v!
17718:07 <stickies-v> we'll have the second part of this meeting tomorrow at 5PM UTC
17818:07 <michaelfolkson> Thanks stickies-v! Struggled with this one
17918:07 <stickies-v> so i hope to see you all again there!
18018:07 <stickies-v> #endmeeting

Meeting 2

18117:00 <stickies-v> #startmeeting
18217:00 <stickies-v> hi everyone, welcome to the second part of our review club on #28956
18317:01 <vmammal> hi
18417:01 <stickies-v> the notes and questions are available at https://bitcoincore.reviews/28956
18517:01 <michaelfolkson> hi
18617:01 <dergoegge> hi
18717:01 <alfonsoromanz> hi everyone
18817:01 <lightlike> Hi
18917:01 <pablomartin> hello
19017:02 <TheCharlatan> hi
19117:02 <Guest3466> hi
19217:02 <henmeh> hi
19317:02 <Ayelen> hi
19417:02 <stickies-v> today we'll be focusing less on the concept and more on the code, sooo let's get technical!
19517:03 <stickies-v> (for anyone that missed yesterday's meeting: yesterday's logs are also on https://bitcoincore.reviews/28956)
19617:03 <emzy> hi
19717:03 <stickies-v> 10. Which operations were relying on network-adjusted time prior to this PR?
19817:04 <alfonsoromanz> TestBlockValidity function
19917:05 <stickies-v> yup, that's one! what else we got?
20017:07 <brunoerg> hi
20117:07 <instagibbs> ContextualCheckBlockHeader
20217:08 <vmammal> `ChainstateManagerOps`  member adjusted_time_callback
20317:08 <alfonsoromanz> m_max_commitments variable to keep a memory of how many commitments we should store from a peer
20417:08 <stickies-v> instagibbs: yea indeed that's the function TestBlockValidity is calling that does the actual timestamp checking
20517:08 <instagibbs> err yeah AcceptBlockHeader :P consensus check on block header
20617:09 <stickies-v> alfonsoromanz: indeed!
20717:10 <alfonsoromanz> the CreateNewBlock function from miner module
20817:11 <michaelfolkson> I'm not seeing where say timelocks were relying network adjusted time... They're not right?
20917:12 <stickies-v> alfonsoromanz: yes we use it to generate new block templates too
21017:12 <stickies-v> michaelfolkson: no they're not, that's Median Time past
21117:12 <michaelfolkson> stickies-v: ah thanks
21217:13 <Ayelen> CanDirectFetch function on Peer Manager
21317:13 <stickies-v> Ayelen: good find!
21417:14 <stickies-v> this is just to highlight that the PR doesn't just affect block validity, but there are other implications too, which we need to validate
21517:15 <stickies-v> does anyone see any problems with switching those callsites to system time? (besides the attack vectors discussed in yesterday's meeting)?
21617:17 <stickies-v> in the interest of time, i'll launch the next question already but always feel free to keep discussing previous questions
21717:17 <stickies-v> 11. Does this PR introduce any difference in how and when it warns for a clock that appears out-of-sync with the network?
21817:17 <grndslm> is it possible for time servers to be hacked and to influence blocks?
21917:17 <michaelfolkson> Still has a SetMedianTimeOffsetWarning
22017:18 <grndslm> just a thought.... i thought the wonder of bitcoin was that there was no oracle, but seems like usine time servers is introducing the first oracle..
22117:18 <stickies-v> grndslm: yes, time servers are a possible source of problems, but that's what we discussed in yesterday's meeting
22217:19 <stickies-v> grndslm: well, you don't need to use time servers?
22317:20 <michaelfolkson> But calls getblockchaininfo now
22417:21 <vmammal> i saw in the PR discussion, stickies-v mentioned that a warning is removed from the gui client
22517:21 <stickies-v> michaelfolkson: the warning doesn't call any RPCs, it just adds the warning to some RPC responses if a user calls the RPC
22617:22 <stickies-v> vmammal: well, trust don't verify, right? where's the code change that does that?
22717:22 <stickies-v> *verify don't trust :( :(
22817:22 <vmammal> lol
22917:24 <lightlike> I think the warnings after this PR are fetch-only (you have to call a RPC to see it). Before the PR it was push (entry in the log, + popup in the gui).
23017:25 <michaelfolkson> Should still be logged though right?
23117:26 <stickies-v> lightlike: indeed! well, except that previously it was push and pull, it also was shown in certain RPCs through https://github.com/bitcoin/bitcoin/blob/3a0f54dd2402d74a5ac4304b3ad09014cfb25edf/src/timedata.cpp#L97
23217:26 <michaelfolkson> When the warning is displayed
23317:26 <stickies-v> michaelfolkson: I feel quite strongly about adding it to logging too, yes
23417:27 <stickies-v> is there any behaviour change in *when* the warning is raised?
23517:28 <vmammal> same 70m threshold
23617:29 <michaelfolkson> That's the default
23717:29 <michaelfolkson> That could be changed by the user
23817:30 <alfonsoromanz> my best guess: prior to the PR the warning was emitted after the offset is calculated (i.e after reaching 199 samples offsets?)
23917:30 <alfonsoromanz> not sure about now. Maybe it's dynamic?
24017:32 <michaelfolkson> The warning is only displayed if the user calls a RPC and not otherwise. That's what you said right stickies-v?
24117:33 <stickies-v> see https://github.com/bitcoin-core-review-club/bitcoin/commit/e7df61b1371bb0a44973bba33d4ea6823dc5f36b#diff-6875de769e90cec84d2e8a9c1b962cdbcda44d870d42e4215827e599e11e90e3R3620-R3624
24217:34 <stickies-v> the warning can be emitted anytime we get a VERSION message from a peer, which is similar to before this PR
24317:34 <stickies-v> it is emitted when the offset is too large, which is also similar to before this PR
24417:35 <stickies-v> but as initially highlighted by naumenkogs, we currently warn as soon as we have 4 samples (i.e. peers connected) when previously this was 5 samples: https://github.com/bitcoin/bitcoin/pull/28956#discussion_r1433684385
24517:37 <stickies-v> 12. `TimeOffsets` has a size of `199`, but `CMedianFilter` was initialized with a size of `200`. What explains this difference?
24617:37 <stickies-v> (link 1: https://github.com/bitcoin-core-review-club/bitcoin/commit/d079ffc9b8e9a81eb0bfb3da66f64c0257f16e71#diff-6875de769e90cec84d2e8a9c1b962cdbcda44d870d42e4215827e599e11e90e3R194)
24717:37 <stickies-v> (link 2: https://github.com/bitcoin/bitcoin/blob/3a0f54dd2402d74a5ac4304b3ad09014cfb25edf/src/timedata.cpp#L41-L44)
24817:37 <lightlike> only VERSION messages from outbound peers though, and we have another unconditional logging msg for these already. So disk-filling attacks via log messages are-not an issue here.
24917:38 <stickies-v> oh right that's a very good addition, thank you lightlike!
25017:38 <michaelfolkson> I don't really understand why there was an odd check on the number of elements in g_time_offsets
25117:40 <vmammal> it's a mystery
25217:42 <alfonsoromanz> michaelfolkson I believe it's because when a number set is odd, then the median ends up being the number "in the middle"
25317:42 <stickies-v> alfonsoromanz: but the `CMedianFilter::median()` functionality explicitly handles containers of even size
25417:44 <stickies-v> no one any ideas to Q12?
25517:44 <vmammal> i thought michaelfolkson had it. the oddness check in AddTimeData
25617:45 <michaelfolkson> Oh it isn't related to this odd/even thing? I assumed it was, sorry
25717:45 <Ayelen> https://github.com/bitcoin/bitcoin/issues/4521 this issue explains unexpected behavior using 200
25817:47 <stickies-v> oh, i didn't interpret it that way, sorry
25917:47 <stickies-v> well no there's a different reason
26017:48 <stickies-v> CMedianFilter used a container of size 200, but it was also initialized with an offset of 0, essentially leaving 199 "real" inputs
26117:48 <stickies-v> see https://github.com/bitcoin/bitcoin/blob/3a0f54dd2402d74a5ac4304b3ad09014cfb25edf/src/timedata.cpp#L44 and the constructor of CMedianFilter
26217:49 <stickies-v> Ayelen: the issue you linked is more about making it explicit that we never go above 200 (which, from what i understand from my perusal of historical PRs, was never intended, but eventually kept to address other, undisclosed, vulnerabilities)
26317:50 <Ayelen> got it, thanks!
26417:50 <stickies-v> 13. Which of the values {0, 5, -2, 50s, 70m} are valid inputs for `-maxtimeadjustment`?
26517:51 <michaelfolkson> int64
26617:52 <michaelfolkson> Signed integer
26717:53 <lightlike> also, for many years timedata was also from taken from inbound peers, not just outbounds. So it was pretty easily to manipulate for an attacker, that could make multiple connections to you. Stopping at 199 samples was a slightly crude way to prevent that, because once the node was running for a few hours/days it was "safe" from this attack.
26817:53 <stickies-v> michaelfolkson: we're talking about user input here though
26917:54 <stickies-v> lightlike: ah, that's good background, thanks for sharing
27017:54 <vmammal> 13. I tried passing each of these to core, all with no issue
27117:55 <alfonsoromanz> I see that there are no validations, i.e: ArgsManager::ALLOW_ANY
27217:55 <vmammal> though -2 seems redundant, as time offset implies +/-
27317:55 <stickies-v> you can read more about the change lightlike mentioned at https://github.com/bitcoin/bitcoin/pull/23631
27417:56 <stickies-v> vmammal: indeed! so technically, they're all "valid", surprisingly
27517:57 <stickies-v> so what happens when we run `bitcoind -maxtimeadjustment 70m`?
27617:57 <stickies-v> vmammal: what do you mean with redundant?
27717:57 <pablomartin> lightlike, stickies-v: insteresting (#23631)... not that long ago...
27817:58 <vmammal> stickies-v simply passing positive 2 would have the same effect. or is that not the case?
27917:59 <stickies-v> alfonsoromanz: indeed, validation on cli arguments is only partially implemented (unlike the RPC args validation which is more extensive), see https://github.com/bitcoin/bitcoin/blob/737e5884cc82dc352cef3ef26abc1cb8d3500b8b/src/common/args.h#L103-L110
28017:59 <stickies-v> vmammal: no, it doesn't. and interestingly, the resulting behaviour is different on master versus on #28956
28117:59 <vmammal> oh geez
28218:00 <michaelfolkson> ha
28318:01 <stickies-v> previously, negative values would get floored at 0: https://github.com/bitcoin/bitcoin/blob/3a0f54dd2402d74a5ac4304b3ad09014cfb25edf/src/timedata.cpp#L81
28418:02 <stickies-v> now, we don't have that anymore: https://github.com/bitcoin-core-review-club/bitcoin/commit/e7df61b1371bb0a44973bba33d4ea6823dc5f36b#diff-a0e6a08e5970d9070be6837f51f6c30b04e9a512fd12ee8d7548753c476f8a62R27
28518:03 <stickies-v> i'll leave the effects of that as a small exercise to the reader, because we are unfortunately at time already
28618:03 <stickies-v> thanks everyone for joining again, and dergoegge for authoring the PR!
28718:03 <vmammal> thanks stickies-v dergoegge
28818:04 <michaelfolkson> Thanks both!
28918:04 <stickies-v> #endmeeting