본문 바로가기
카테고리 없음

채굴 난이도 조절 방식, 타임스탬프

by 3min⚡️bitcoin 2025. 12. 9.

채굴, 작업증명이 뭔지 모르겠다면 우선 이거부터 추천한다.

https://3min-bitcoin.tistory.com/12

 

비트코인 채굴과 작업증명과(PoW)

가끔 뉴스를 보다보면 비트코인 솔로 채굴에 성공하여 3BTC 가량을 독식했다며 부러움을 자아낸다. (솔직히 개부럽다)혹은 비트코인 채굴 반감기가 도래하여 4년 주기 사이클이라 이제 상승기다,

3min-bitcoin.tistory.com

채굴 난이도 조절은 어떻게?

제네시스 블록의 채굴 난이도를 1.0으로 두고 현재 채굴하기 얼마나 어려운지 나타내는 값이 채굴 난이도이다.

 

비트코인은 한 개의 블록 채굴 시간이 평균적으로 10분이 되도록 맞춰져있다.

비트코인은 2016개 블록이 채굴될 때마다 난이도가 조절된다. 약 2주정도?

 

만약 2016개 채굴이 20160분 보다 적게 걸렸으면 난이도가 상승하고, 오래 걸렸으면 난이도가 하락한다.

채굴 난이도 조정 공식

 

만약 20000분이 걸렸다? 위 수식에 대입하면 난이도는 1.008, 0.8% 정도 상승하게 된다.

unix timestamp - learnmeabitcoin

위에 설명한 걸린 시간같은 경우는 어떻게 판별할까?

바로 블록 헤더의 time 값을 보고 판단한다.

 

하지만 time(타임스탬프) 값은 각 컴퓨터의 로컬 타임에 오차가 있기도 하고, 데이터가 전송되는 시간도 있기 때문에 절대적일 수 없다.

게다가 time값은 채굴자가 임의로 넣을 수 있다. 실제로 time값이 이전 블록보다 먼저일 수도 있다. 

이를 음수 기간 사건(negative duration event) 이라고 한다.

negative duration event 발생한 사례

918962는 2025-10-14 12:53:22, 918963번 블록은 2025-10-14 12:50:25 로 먼저 채굴된 블록의 시간이 더 뒤에있다.

 

이는 앞서 말한 것 처럼 타임스탬프 값이 절대적인 시각도 아니고 채굴자가 임의로 넣을 수 있기에 종종 발생하기도 한다.

난이도 조절에 이 값이 사용되는데, 채굴자가 악의적으로 난이도를 본인 입맛에 맞게 조절하기 위해 시간을 터무니없는 값을 입력하면 어떻게 될까? time값으로 난이도 조절 공격을 한다면..?!

 

채굴자가 아주 먼 미래 값을 넣어 채굴 난이도를 쉽게 하려고 한다면?

위 공식에서 분모값을 아주 크게 해서 난이도를 대폭 낮추는 공격이다.

난이도를 낮추면 채굴자는 채굴이 쉬워짐에 따라 적은 비용 투자로 높은 보상을 마구 받을 수 있기 때문에 조작할 이유가 있다.

 

하지만 비트코인은 Future Block Time(미래 블록 시각)이라는 규칙이 존재한다.

이는 2시간 이상 미래의 timestamp값을 입력할 수 없다는 내용이다.

// src/chain.cpp
static constexpr int64_t MAX_FUTURE_BLOCK_TIME = 2 * 60 * 60; // 7200초

// src/validation.cpp ContextualCheckBlockHeader 함수 4210번 line
// Check timestamp
if (block.Time() > NodeClock::now() + std::chrono::seconds{MAX_FUTURE_BLOCK_TIME}) {
    return state.Invalid(BlockValidationResult::BLOCK_TIME_FUTURE, "time-too-new", "block timestamp too far in the future");
}

 

위 코드는 블록의 타임값이 현재 시간(NodeClock::now())에 7200초(2시간) 더한 값(std::chrono::seconds{MAX_FUTURE_BLOCK_TIME})보다 크다면 검증 실패 처리를 한다는 코드이다.

 

고로, 실제로 의도적으로 2016번째 블록을 채굴하여 난이도를 낮추려면 최대 2시간이고, 최대 0.6% 정도 쉬워지게 만들 수 있다.

채굴자가 난이도를 매우 어렵게 해서 다같이 죽자고 한다면?

위 공식에서 분모를 매우 작게 해서 난이도를 대폭 상승해서 채굴을 못하게 하는 공격이다.

이는 본인의 인센티브도 포기하는것이므로 비트코인 시스템 자체에 대한 악감정이 동기가 될 수 있겠다.

 

이를 막기 위해서, 비트코인에는 MTP(Median Time Past) 중간 과거 시각 규칙이 있다.

이는 새로운 블록의 타임값이 이전 블록 11개의 타임값의 중앙값보다 더 커야 한다는 것을 말한다.

 

bitcoin time - learnmeabitcoin

 

위 그림에서 윗 부분이 Future Block Time, 아래 부분이 Median Time Past 이다.

이 경우 최대 60분 정도의 오차를 만들어낼 수 있으며 이는 최대 0.3% 정도 어렵게 만들 수 있다.

 

검증자의 현재 시간은 어떻게 구하는가?

위 소스코드에서 NodeClock::now() 가 현재시간을 구하는 로직이다.

잠깐 생각해보면, 검증하는 사람의 시간도 절대적이지 않고 잘못되어있을 수 있다.

Network Adjust Time 네트워크 조정 시간

network adjust time - learnmeabitcoin

 

그래서 등장했던 개념이 Network Adjust Time (네트워크 조정 시간)으로, 주변 노드들의 시간을 받아서 조정한다는 개념이다.

실제로 피어 노드들로부터 받는건 시간값은 아니고, 내 시간값과의 차이값이다.

그리고 피어 노드들의 차이값을 offset이라 하고, 그 중앙값을 Median Offset이라 한다.

내 현재 로컬 시간에 Median Offset을 더하면 Network Adjust Time이 된다.

 

이 오프셋을 구하기 위해 필요한 피어는 최소 5개이며, 모두 아웃바운드 노드여야 한다.

비트코인 코어 27 이후부터 달라진 현재시간 구하는 방식

그런데 실제로 비트코인 코어 소스코드를 보면 현재 시간을 구하는 방식이 조금 달랐다.

// src/time.cpp 코드
NodeClock::time_point NodeClock::now() noexcept
{
    const auto mocktime{g_mock_time.load(std::memory_order_relaxed)};
    if (!mocktime.count()) {
        g_used_system_time = true;
    }
    const auto ret{
        mocktime.count() ?
            mocktime :
            std::chrono::system_clock::now().time_since_epoch()};
    assert(ret > 0s);
    return time_point{ret};
};

 

 

 

해석하자면, 테스트환경이 아니라면 내 시스템의 로컬 시간을 현재 시간으로 쓰겠다는 코드이다.

 

분명, 시간을 조작해서 공격을 하는게 문제일 것 같은데 왜 그냥 사용하는가?

 

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

반영은 위 PR에서 진행되었다.

반영 당시 진행된 토론들을 읽어보면 adjust time을 사용하는게 NTP(Network Time Protocol) 기반 공격에 대해 효과적이지 않다고 판단해서 없앴다고 한다.

오히려 임의의 다수 피어에 의존하지 않도록 하는걸 더 좋다고 판단한 것이다.

왜냐하면, 악의적으로 주변 피어에 이상한 시간을 주입하는 공격이 더 위험하다고 본 것 같다.

 

따라서 결론적으로는 현재 시간을 구하는 것은 OS 레벨의 NTP 클라이언트를 이용하는 형태이다.

이건 내 생각인데, 이것도 결국 비잔틴 결함 허용처럼, 풀노드 운영자들이 굳이 OS 레벨의 NTP 시간을 조작할 동기가 없고,

주변 피어들에 의존하는 포인트를 제거하는 방향으로 간게 아닌가 하는 생각이다.

 

++ NTP서버는 컴퓨터 시계 시간을 동기화 하는데 사용하는 것으로 외부에서 시간을 가져와서 내 컴퓨터에 동기화 하는 것. 여기서 말하는 외부는 ISP, 대기업등 표준시간을 제공하는 기관들이 모여서 Pool을 이루었다. 보통 거기랑 연결되어있다.

 

참고문헌

https://learnmeabitcoin.com/technical/block/time/

 

Time | Block Header Field

Time Rough time a block was created The time field in the block header indicates the rough time a block was created. Miners put the current time in the block header when they construct their candidate block. It contains a Unix Timestamp (the number of seco

learnmeabitcoin.com

 

https://bitcoin.stackexchange.com/questions/7404/how-does-bitcoin-figure-out-what-time-it-is

 

How does Bitcoin figure out what time it is?

Bitcoin needs to know the current time in order to validate blocks. How does it decide that? Note that I'm talking about the Satoshi client specifically.

bitcoin.stackexchange.com

 

https://bitcoin.stackexchange.com/questions/121247/how-exactly-is-the-timestamp-calculated-for-the-2h-acceptance-rule-and-do-i-hav

 

How exactly is the timestamp calculated for the +2h acceptance rule and do I have to implement it in my Bitcoin node for the nod

In recent times, I have read many articles and questions/answers on bitcoin.stackexchange related to the timestamp, but I still have problems understanding certain things. They are related to the

bitcoin.stackexchange.com

 

https://en.bitcoin.it/wiki/Protocol_rules

 

Protocol rules - Bitcoin Wiki

Rules for clients. The wiki substantially documents the Bitcoin protocol, but equally important are the rules used by the client to process messages. It's crucial that clients follow certain rules in order to maintain consistency across the network, and to

en.bitcoin.it