계: Time and State

분산 컴퓨팅에서 중요한 것은 시간과 상태입니다. 즉, 둘 이상의 구성 요소가 통신하려면 상태를 공유해야 하며 시간이 걸립니다.

대부분의 프로그래머들은 자신들의 작업을 의인화합니다. 하나의 컨트롤 스레드로 마치 자신이 직접 작업한 것처럼 전체 프로그램을 수행할 수 있을 것으로 생각합니다. 하지만 최신 컴퓨터는 작업 간에 매우 빠르게 전환되므로 멀티코어, 멀티 CPU 또는 분산 시스템에서 두 이벤트가 정확히 동시에 발생할 수 있습니다. 프로그래머가 만든 프로그램 실행 모델과 실제 현실 간에 빠르게 결함이 생기기 마련입니다. 이러한 결함은 스레드, 프로세스, 시간 및 정보 간의 예기치 않은 상호작용과 관련이 있습니다. 이러한 상호 작용은 공유 상태를 통해 발생합니다. 세마포, 변수, 파일 시스템 그리고 정보를 저장할 수 있는 모든 것이 여기에 포함됩니다.

Often Misused: Block Values

Abstract
함수가 시간의 프록시로 block.timestamp 또는 block.number를 사용합니다.
Explanation
개발자는 흔히 block.timestamp 또는 block.number에 연결된 값을 사용해 시간 종속 이벤트를 트리거합니다. 그런데 이러한 값은 대개 사용하기에 안전하지 않은 시간 정보를 제공하는 경우가 많습니다.

블록체인은 분산형 기술이므로 노드는 시간을 특정 수준까지만 동기화할 수 있습니다. block.timestamp를 사용하는 코드는 신뢰하기가 어려울 수 있으며 최악의 경우에는 악의적인 채굴자가 블록의 타임스탬프를 채굴에 유리하게 변경할 수도 있습니다.

block.number 사용 시에는 블록 간 시간(약 14초) 예측은 가능하지만 블록 시간이 일정하게 유지되지 않으며 네트워크 활동에 따라 달라질 수도 있습니다. 그러므로 block.number는 시간 관련 계산에서 안전하게 사용할 수 없습니다.

예제 1: 다음 코드는 block.number를 사용하여 일정 기간이 지난 후 자금을 잠금 해제합니다.


function withdraw() public {
require(users[msg.sender].amount > 0, 'no amount locked');
require(block.number >= users[msg.sender].unlockBlock, 'lock period not over');
uint amount = users[msg.sender].amount;
users[msg.sender].amount = 0;
(bool success, ) = msg.sender.call.value(amount)("");
require(success, 'transfer failed');
}
References
[1] Enterprise Ethereum Alliance Don't misuse block data
[2] Standards Mapping - CIS Azure Kubernetes Service Benchmark 2.0
[3] Standards Mapping - CIS Amazon Elastic Kubernetes Service Benchmark 2.0
[4] Standards Mapping - CIS Amazon Web Services Foundations Benchmark 3
[5] Standards Mapping - CIS Google Kubernetes Engine Benchmark normal
[6] Standards Mapping - Smart Contract Weakness Classification SWC-116
desc.structural.solidity.swc116