common/math 패키지

big.go

  • big.Int 타입과 관련된 타입과 유틸리티 함수들이 정의되어 있습니다.

2의 보수

  • 어떤 수를 커다란 2의 제곱수에서 빼서 얻은 2진수를 2의 보수라고 합니다.
  • 2의 보수를 사용하는 이유는 음수를 부호가 없는 정수(unsigned integer)로 표현하기 위해서입니다.
  • 이 때 부호가 없는 정수는 이더리움에서 사용하는 256비트 uint256 타입의 정수입니다.
// U256은 큰 정수를 256비트 2의 보수 숫자로 인코딩합니다. 이 연산은 파괴적(원본값을 변경)입니다.
func U256(x *big.Int) *big.Int {
	// x가 양수인 경우: x & tt256m1 -> x 자기 자신을 반환 
	// x가 음수인 경우: (2**256 - 1) & (-x) = (2**256 - 1) &^ (x - 1) -> x의 2의 보수를 반환 (여기서 x - 1은 양수 x의 모든 비트를 반전시킨 값)
	// 빼기 연산을 사용하지 않은 이유: x가 양수인 경우 2**256 - x는 완전히 다른 값이 되므로
	return x.And(x, tt256m1)
}

// S256은 2의 보수 x를 부호가 있는 256비트 숫자로 인코딩합니다.
// x는 256비트를 초과해서는 안됩니다(그렇게 되면 결과는 정의되지 않음). 
// 이 연산은 파괴적(원본값을 변경)이지 않습니다.
//
//	S256(0)        = 0
//	S256(1)        = 1
//	S256(2**255)   = -2**255
//	S256(2**256-1) = -1
func S256(x *big.Int) *big.Int {
	if x.Cmp(tt255) < 0 { // x < 2**255 (왜 2**255보다 작으면 양수로 취급하는가?)
		return x
	}
	return new(big.Int).Sub(x, tt256) // x - 2**256
}

integer.go

  • 정수와 관련된 타입과 도우미 함수들이 정의되어 있습니다.