# Coinbase 만기 규칙 (A.K.A 출력 )

Coinbase 산출물 (블록 보상 및 수수료)은 "잠겨"있고 쓰는 것이 가능하기 전에 1,440개의 충분한 확인 (즉, 체인에 추가 된 이후 24 시간정도의 확인, *블록이 추가된 후 24시간 정도의 확인이 필요하다는 뜻 - 역자 주*)이 필요합니다. 이것은 체인 재구성(chain reorganization)이 발생할 경우 나중에 txs가 되돌려질 위험을 줄이기위한 것입니다.

Bitcoin도 비슷한 과정을 거칩니다. Bitcoin은 마이닝 보상을 쓰기 전에 100 회의 확인 (Bitcoin 블록은 매 10 분, Grin 블록은 매 60초)을 수행합니다.

Grin은 트랜잭션 풀과 블록입증(block validation) 파이프라인(Pipeline) 둘다 코인베이스 만기 규칙을 강제합니다. 코인베이스 출력을 사용하는 입력을 포함하는 트랜잭션은 현재 체인 높이와 코인베이스 출력을 생성하는 블록의 높이를 기준으로 충분히 만기가 될 때까지 트랜잭션 풀에 추가 될 수 없습니다. 블록에서도 (트랜잭션 과)비슷하게 입력을 포함하는 블록의 높이와 원래 코인베이스 출력을 생성 한 블록의 높이를 기준으로 충분히 만기가 되기 전에 코인베이스 출력을 소비하는 입력을 포함하면 유효하지 않습니다.

*만기 규칙( Maturity rule)은 코인베이스 출력에만* 적용 됩니다. 일반적인 트랜잭션 출력은 유효한 lock height가 0입니다(Zero confirm 이라는 뜻- 역자 주).

출력값은 아래와 같은 값으로 이뤄집니다.

* 기능 (현재의 코인베이스 VS non-코인베이스)
* `rG+vH` 실행값(commitment)
* rangeproof

기존 트랜잭션 출력을 사용하려면 두 가지 조건이 충족되어야 합니다. 출력이 이전에 쓰지 않았다는것 을 보여주어야하며 출력의 소유권(ownership of output)을 증명해야합니다.


Grin 트랜잭션은 다음과 같이 구성되어 있습니다.

* 입력값의 셋, 각 입력값은 이전 소비된 출력값에 대해서 참조합니다.
* 새로운 출력값들의 셋은 다음과 같은 요소를 포함합니다.
  * `v`값과 비밀키이자 Bliding factor인 `r`과 타원곡선 값이 곱해지고 더해진 값인 `rG+vH`(commitment 값이기도 함)
  * `v`값이 음수가 아님(non-negative)을 보여줄 range proof
* 명백한 트래잭션 수수료
* 모든 출력값에 수수료를 더하고 입력값을 뺀 초과 Blinding factor 로 계산하고 비밀키로 사용된 서명 값

현재 출력 셋에서 실행값(`rG+vH`, commitment값 - 역자 주)을 찾음으로써 출력이 미사용 상태임을 나타낼 수 있습니다. 만약 출력이 출력셋에 존재하는 경우 아직 사용되지 않았다는 것을 알 수 있기 때문에 출력셋은 신뢰할 수 있습니다. 출력이 출력 셋에 존재하지 않는다면 출력값이 존재하지 않았거나 이전에는 있었고 소비되었음을 알 수 있습니다 (필연적으로 출력셋이 존재하지 않았던 것이든 이전에 있었던 것이든 어떤 것이든 알지 못할 것입니다).

소유권을 증명하기 위해 트랜잭션 서명을 입증할 수 있습니다. 트랜잭션의 합이 0이 되고 *그리고* `v`와 `r`을 모두 알고있는 경우에만 *오직* 트랜잭션에 서명 할 수 있습니다.

`v`와 `r`을 알면 우리는 출력을 실행값(commitment)을 통해 구분 할 수 있습니다. *그리고* 원래 코인베이스 트랜잭션에서 서명의 유효성을 검사하여 출력의 소유권을 증명할 수 있습니다.

Grin은 동시에 출력 셋에 중복된 실행값(commitment)이 존재하는 것을 허용하지 않습니다. 그러나 일단 출력이 소비되면 출력 셋에서 제거되고 중복된 실행값(commitment)이 출력 셋에 다시 추가 될 수 있습니다.
이것은 반드시 권장하지 않지만 Grin은 네트워크를 통해 합의를 깨지 않는 방식으로 이런 상황을 처리해야합니다.

아래와 같은 몇 가지가 이런 상황을 복잡하게 만듭니다.

1. 특히 빈 블록의 경우 두 블록이 동일한 보상을 받을 수 있습니다. 뿐만 아니라 거래 수수료가 있는 비어 있지 않은 블록의 경우에도 가능합니다.
1. 코인베이스 출력이 아닌 출력값이 코인베이스 출력과 동일한 값을 가질 수 있습니다.
1. 권장되진 않지만 마이너가 비밀키(private key)를 재사용 할 수 있습니다.

Grin은 동시에 출력 셋에 중복된 실행값(commitment)이 존재하는 것을 허용하지 않습니다. 그러나 출력 셋은 특정 체인 분리(fork)의 상태에 따라 다릅니다.
같은 순간에 있는 서로 다른 체인에 중복 된 *동일한* 실행값(commitment)가 동시에 *존재할 수 있습니다*. 그리고 이러한 중복된 실행값은 다른 "lock height"를 가질 수 있습니다. 그리고 각각 다른 체인에서 이런 실행값들은 코인베이스 만기가 다 되어서 소비 할 수 있수도 있습니다. 

* block B<sub>1</sub>에서 온 출력값 O<sub>1</sub> 소비 가능한 높이는 h<sub>1</sub> (체인 f<sub>1</sub>)
* block B<sub>2</sub>에서 온 출력값 O<sub>1</sub>' 소비 가능한 높이 h<sub>2</sub> (체인  f<sub>2</sub>)

여기서 복잡한 점은 입력 I<sub>1</sub>을 포함하는 블록이 있는 포크에 따라 O<sub>1</sub> 또는 O<sub>1</sub>'을 사용한다는 것입니다. 그리고 결정적으로 I<sub>1</sub>은 어떤 체인에서는 특정 블록 높이에서 유효하지만 다른 포크에서는 유효하지 않을 수 있다는 것입니다.

다른 말로 하자면, 실행값은 여러 개의 출력을 의미 할 수 있으며, 모든 출력은 서로 다른 lock height를 가질 수 있습니다.
그리고 우리는 어떤 결과가 실제로 소비되고 있는지, 코인베이스 만기 규칙이 현재의 체인 상태(chain state)를 기반으로 정확하게 시행되고 있는지 정확하게 *반드시 확인해야 합니다.*

특정 lock height에서 coinbase 만기 규칙으로 잠긴 코인베이스 출력은 고유하게 확인될 수 *없습니다*. 그리고 자신의 실행값 만으로는 안전하게 사용할 수 *없습니다.*
코인베이스 출력을 사용하려면 아래와 같이 추가적인 요소 하나를 알아야 합니다.

* 코인베이스 출력값이 어디서 나왔는지 기록되어 있는 블록(The block the coinbase output originated from 라고 원문에 표기되어 있음 -역자 주)

이 경우 블록의 높이를 검증하고 출력물의 "lock height"(+ 1000 블록)를 알아 낼 수 있습니다.

## 풀 아카이브 노드

풀 아카이브 노드가 있으면 출력이 어느 블록에서 시작되었는지 식별하는 것은 간단한 작업입니다. 전체 아카이브 노드는 다음을 저장합니다.

* 체인 내에 있는 전체 블록의 모든 블록 데이터
* 해당 블록들 안에 있는 전체 출력값의 모든 출력값 데이터

체인의 이전의 모든 블록을 볼 수 있으며 특정 출력이 들어있는 블록을 찾을 수 있습니다.

문제는 전체 블록 데이터가 없는 노드(Pruning 노드, 아카이브 노드가 아닌 노드)를 고려해야 할 때입니다.

전체 블록 데이터가 없더라도 코인베이스 만기에 대해서 어떻게 입증 할 수 있을까요??

## 비 - 아카이브 노드(non - achive node)

A node may not have full block data.
A pruned node may only store the following (refer to pruning doc) -
노드에는 전체 블록 데이터가 없을 수 있습니다. pruning 노드는 다음을 저장할 수 있습니다 ([프루닝 문서 참조](pruning_KR.md)).

* 블록 헤더 체인
* All transaction kernels.
* 전체 트랜잭션 커널(kernels)
* 전체 미사용된 출력값(unspent outputs)
* 출력값의 MMR 과 range proof MMR

이 최소한의 데이터 셋을 가지고 어느 블록에서 시작되었는지 어떻게 알 수 있습니까?

주어진 데이터로 여러 출력(여러 포크, 잠재적으로 서로 다른 lock height)이 모두 *같은* 실행값을가질 수 있는지, 사용한 출력을 고유하게 식별하기 위해 입력값에 어떤 추가 정보가 필요한가요?

그리고 한 단계 더 나아가기 간다면 전체 출력 데이터에 액세스하지 않고도 이 모든 작업을 수행 할 수 있을까요? 출력 MMR만 사용할 수 있나요?

### 제안된 해결법

출력 MMR 내에서 위치의 인덱스 매핑 실행값을 유지합니다.

인덱스에 항목이 없거나 주어진 실행값에 대해 출력 MMR내에서 항목이 존재하지 않으면 출력값은 사용할 수 없습니다. (이전에 소비되었거나 아예 존재하지 않았음).

출력 MMR에서 항목을 찾으면 쓸 수 있는 출력이 출력셋에 있음을 알 수 있습니다. *하지만* 이것이 올바른지 여부는 알 수 없습니다. 코인베이스 출력인지 아닌지와 그 블록이 시작된 블록의 높이를 알지 못합니다.

출력 MMR에 저장된 해시가 실행값(commitment)및 출력 기능을 모두 포함하고 실행값과 기능을 모두 제공하기 위해 입력이 필요한 경우 아래와 같은 추가 검증 단계를 수행 할 수 있습니다.

* 실행값 베이스의 출력값 MMR 내에 출력값이 있고
* MMR의 해시는 입력에 포함 된 출력 데이터와 일치합니다.

이 추가 단계를 통해 출력이 코인베이스 출력인지 또는 제공된 기능을 기반으로 하는 일반적인 트랜잭션 출력인지 여부를 알 수 있습니다. 입력값이 원래 출력값과 일치하지 않으면 해시가 일치하지 않습니다.

일반적인 non-coinbase 출력에 대해서 설명은 이미 끝냈습니다. 출력값은 현재 쓸 수 있으므로 lock height를 확인할 필요가 없습니다.

코인베이스 출력의 경우 lock height와 블록 만기를 검증 할 수 있습니다. 이를 위해 출력이 발생한 블록을 식별해야합니다.
블록 자체를 결정할 수는 없지만 블록 해시을 특정하기 위해서 입력을 필요 할 수 있습니다. 그런 다음 전체 블록 데이터 없이 블록 헤더의 머클 루트를 기반으로 증명할 수 있습니다.

[추후에 결정될 것 - 머클 proofs의 개요와 블록헤더 안의 머클 루트 (merkle root)기반으로 어떻게 머클 proofs 를 사용하여 포함된 것을 증명 할 것인가 ]

요약하자면 -

실행값(commitment) 자체만으로는 충분하지 않기 때문에 출력 MMR은 `commitment | features`을 기반으로 출력 해시를 저장합니다 .
출력 해시 생성시 range proof를 포함 할 필요가 없습니다.
출력값을 소비하기 위해 아래와 같은 것이 필요합니다. -

* `r`과 `v`는 실행값(commitment)을 만들고(build) 소유권을 증명합니다.

입력값은 아래와 같은 값을 반드시 포함해야 합니다.

* MMR 내에서 찾은 실행값 ( commitment)
* 출력값 (features|commitment 에 따른 출력값 MMR 의 해시)
* 원래 불록 내에서의 Merkle proof 를 포함하는 출력값
* 원래 블록의 블록 해시
  * [추후에 결정될 것 - Merkle proof 기반 인덱스를 유지할 것인가?]
실행값(commitment)과 기능을 통해 올바른 출력이 현재 사용되지 않은지 확인할 수 있습니다.
블록과 출력값로부터 lock height(있는 경우)를 결정할 수 있습니다.