diff --git a/docs/ko/basics/README.md b/docs/ko/basics/README.md new file mode 100644 index 000000000..e78b1cd54 --- /dev/null +++ b/docs/ko/basics/README.md @@ -0,0 +1,17 @@ + + +# Basics + +여기는 Cosmos SDK 의 기초 개념에 대한 참고 문서를 포함하고 있습니다. + +1. [SDK 애플리케이션 해부](./app-anatomy.md) +2. [트랜잭션의 생명주기](./tx-lifecycle.md) +3. [쿼리의 생명주기](./query-lifecycle.md) +4. [계정](accounts.md) +5. [가스와 비용](gas-fees.md) + +기초 개념을 읽고 난 뒤에, [Core](../core/README.md) 에서 심화 내용을 알아보세요. diff --git a/docs/ko/basics/accounts.md b/docs/ko/basics/accounts.md new file mode 100644 index 000000000..ffca52be3 --- /dev/null +++ b/docs/ko/basics/accounts.md @@ -0,0 +1,180 @@ + + +# 계정 (Accounts) + +이 문서는 Cosmos SDK 에 내장된 계정과 공개키 시스템에 대해서 설명합니다. {synopsis} + +### 사전 요구 학습 + +- [SDK 애플리케이션 해부](./app-anatomy.md) {prereq} + +## 계정 정의 (Accounts Definition) + +Cosmos SDK 에서는, 계정이 _공개키_ `PubKey` 와 _개인키_ `PrivKey` 를 지정합니다. `PubKey` 를 파생해서 다양한 `Addresses` 를 생성할 수 있으며, +이를 통해 애플리케이션에서 사용자를 식별할 수 있습니다. 또한 `Addresses` 는 `message` 의 발신자를 식별하기 위한 [`message`들](../building-modules/messages-and-queries.md#messages) 과 연결됩니다. `PrivKey` 는 [디지털 서명](#signatures) 을 생성하여 `PrivKey` 와 연결된 주소가 특정 메시지를 승인했음을 증명하는데에 사용됩니다. + +HD키 파생을 위해 Cosmos SDK 는 [BIP32](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki) 라는 표준을 사용합니다. +BIP32 는 사용자들에게 최초 비밀 시드에서 파생된 계정 세트인 HD 지갑 +([BIP44](https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki) 에 명시) 을 생성하게 해줍니다. 시드는 보통 12 ~ 24 단어의 +니모닉으로부터 생성됩니다. 하나의 시드는 단방향 암호화 기능을 사용하여 원하는 수 의 `PrivKey` 를 파생할 수 있습니다. 그런 다음 `PrivKey` 에서 `PubKey` 를 +파생할 수 있습니다. 개인키는 저장된 니모닉으로부터 얼마든지 다시 생성할 수 있으므로 당연히 니모닉이 가장 민감한 정보가 됩니다. + +``` + 계정 0 계정 1 계정 2 + ++------------------+ +------------------+ +------------------+ +| | | | | | +| ㅤㅤ 주소 0 ㅤ | | 주소 1 | | 주소 2ㅤㅤ ㅤ| +| ^ | | ^ | | ^ | +| | | | | | | | | +| | | | | | | | | +| | | | | | | | | +| + | | + | | + | +|ㅤㅤㅤ 공개키 0 ㅤ | |ㅤㅤㅤ 공개키 1ㅤㅤㅤㅤ| |ㅤㅤㅤ 공개키 2 ㅤ | +| ^ | | ^ | | ^ | +| | | | | | | | | +| | | | | | | | | +| | | | | | | | | +| + | | + | | + | +| ㅤㅤㅤ 개인키 0 ㅤ | ㅤㅤㅤㅤㅤ | ㅤㅤㅤ 개인키 1 ㅤ| ㅤㅤ ㅤ| ㅤㅤㅤ개인키 2 ㅤ| +| ^ | | ^ | | ^ | ++------------------+ +------------------+ +------------------+ + | | | + | | | + | | | + +--------------------------------------------------------------------+ + | + | + +---------+---------+ + | ㅤㅤㅤ | + | 마스터 PrivKeyㅤㅤ | + | ㅤㅤㅤ | + +-------------------+ + | + | + +---------+---------+ + | ㅤㅤㅤ | + |ㅤㅤㅤ 니모닉 (시드)ㅤㅤ | + | ㅤㅤㅤ | + +-------------------+ +``` + +Cosmos SDK 에서는 키는 [`Keyring`](##Keyring) 이라는 객체에 의해 저장되고 관리됩니다. + +## 키, 계정, 주소 그리고 서명 + +사용자 인증의 주요 방법은 [디지털 서명](https://en.wikipedia.org/wiki/Digital_signature) 을 사용하는 것입니다. 사용자는 그들 소유의 개인키를 +사용해서 트랜잭션에 서명합니다. 서명 확인은 연결된 공개키를 통해 수행됩니다. 온체인(on-chain) 서명 확인 목적을 위해서 공개키를 `Account` 객체에 저장합니다. +(올바른 트랜잭션 유효성 검사에 필요한 다른 데이터와 함께) + +노드에서 모든 데이터는 프로토콜 버퍼 직렬화를 사용해서 저장됩니다. + +Cosmos SDK 는 디지털 서명 생성을 위해 다음과 같은 키 체계를 지원합니다. + +- `secp256k1`, [SDK 의 `crypto/keys/secp256k1` 패키지](https://github.com/cosmos/cosmos-sdk/blob/v0.42.1/crypto/keys/secp256k1/secp256k1.go) 에 구현. +- `secp256r1`, [SDK 의 `crypto/keys/secp256r1` 패키지](https://github.com/cosmos/cosmos-sdk/blob/master/crypto/keys/secp256r1/pubkey.go) 에 구현. +- `tm-ed25519`, [SDK 의 `crypto/keys/ed25519` 패키지](https://github.com/cosmos/cosmos-sdk/blob/v0.42.1/crypto/keys/ed25519/ed25519.go) 에 구현. 이 체계는 오직 합의만 지원합니다. + +| | 주소 길이 | 공개키 길이 | 트랜잭션 서명에 사용 | 합의에 사용 (tendermint) | +|--------------|------------|----------|-----------------|-----------------------| +| `secp256k1` | 20 | 33 | 네 | 아니오 | +| `secp256r1` | 32 | 33 | 네 | 아니오 | +| `tm-ed25519` | -- 미사용 -- | 32 | 아니오 | 네 | + +## 주소 (Addresses) + +`Addresses` 와 `PubKey` 는 둘 다 애플리케이션에서 행위자를 식별하는 공개 정보입니다. `Account` 는 인증 정보를 저장하는데에 사용됩니다. 기본 계정의 +구현은 `BaseAccount` 객체를 통해 제공됩니다. + +각 계정은 공개키에서 파생된 바이트 시퀀스인 `Address` 를 사용해 식별됩니다. Cosmos SDK 에서는 3가지의 주소 타입을 정의하는데, 각 주소 타입은 계정이 +사용되는 컨텍스트를 지정합니다. + +- `AccAddress` 는 사용자 (`message` 의 발신자) 를 식별합니다. +- `ValAddress` 는 검증자 (Validator) 오퍼레이터들을 식별합니다. +- `ConsAddress` 는 합의에 참여하는 검증자 노드들을 식별합니다. 검증자 노드들은 `ed25519` 커브를 사용하여 파생됩니다. + +이 타입들은 `Address` 인터페이스를 구현합니다. + ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.42.1/types/address.go#L71-L90 + +주소 생성 알고리즘은 [ADR-28](https://github.com/cosmos/cosmos-sdk/blob/master/docs/architecture/adr-028-public-key-addresses.md) 에 정의되어 있습니다. +다음은 `pub` 공개키로부터 계정 주소를 얻는 표준 방법입니다. + +```go +sdk.AccAddress(pub.Address().Bytes()) +``` + +참고로 `Marshal()` 및 `Bytes()` 메서드는 둘 다 동일한 로우(raw) `[]byte` 형식 주소를 반환합니다. 프로토콜 버퍼 호환성을 위해서는 `Marshal()` 을 +사용해야합니다. + +주소는 [Bech32](https://en.bitcoin.it/wiki/Bech32) 형식을 사용하고 `String` 메서드로 구현됩니다. Bech32 메서드는 블록체인과 상호작용할 때 +사용할 수 있는 유일한 형식입니다. 사람이 읽을 수 있는 Bech32 부분 (Bech32 prefix) 은 주소 타입을 나타내는데 사용됩니다. 예시: + ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.42.1/types/address.go#L230-L244 + +| | Address Bech32 Prefix | +| ------------------ | --------------------- | +| Accounts | cosmos | +| Validator Operator | cosmosvaloper | +| Consensus Nodes | cosmosvalcons | + +### 공개키 (Public Keys) + +Cosmos SDK 의 공개키는 `cryptotypes.PubKey` 인터페이스로 정의됩니다. 저장소에 공개키가 저장되고나면, `cryptotypes.PubKey` 는 +`proto.Message` 인터페이스를 확장합니다. + ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.42.1/crypto/types/types.go#L8-L17 + +`secp256k1` 과 `secp256r1` 직렬화에 압축 형식을 사용합니다. + +- `y` 좌표가 사전식 순서로 `x` 좌표보다 크다면 첫번째 바이트는 `0x02` 가 됩니다. +- 아니라면 첫번째 바이트는 `0x03` 이 됩니다. + +이 prefix 다음에는 `x` 좌표가 붙습니다. + +공개키는 계정(또는 사용자) 참조에 사용되지 않으며 트랜잭션 메시지를 작성할 때 일반적으로 사용되지 않습니다 (몇가지 예외: `MsgCreateValidator`, +`Validator` 와 `Multisig` 메시지들). `PubKey` 는 사용자 상호작용을 위해 프로토콜 버퍼 JSON +([ProtoMarshalJSON](https://github.com/cosmos/cosmos-sdk/blob/release/v0.42.x/codec/json.go#L12) 함수) 포맷으로 맞춰집니다. +예시: ++++ https://github.com/cosmos/cosmos-sdk/blob/7568b66/crypto/keyring/output.go#L23-L39 + +## 키링 (Keyring) + +`Keyring` 은 계정을 저장하고 관리하는 객체입니다. Cosmos SDK 에서 `Keyring` 구현은 `Keyring` 인터페이스를 따릅니다. + ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.42.1/crypto/keyring/keyring.go#L51-L89 + +`Keyring` 의 기본 구현은 서드 파티인 [`99designs/keyring`](https://github.com/99designs/keyring) 라이브러리를 사용합니다. + +`Keyring` 메서드의 몇가지 참고 사항: + +- `Sign(uid string, payload []byte) ([]byte, sdkcrypto.PubKey, error)` 는 `payload` 바이트의 서명을 엄격하게 처리합니다. 트랜잭션은 + 반드시 표준 `[]byte` 형식으로 인코딩해야 합니다. 프로토콜 버퍼는 결정론적이지 않기 때문에, 서명할 표준 `payload` 를 + [ADR-027](adr-027-deterministic-protobuf-serialization.md) 을 사용하여 결정론적으로 인코딩된 `SignDoc` 구조체로 + [ADR-020](../architecture/adr-020-protobuf-transaction-encoding.md) 에서 결정하였습니다. + +++ https://github.com/cosmos/cosmos-sdk/blob/v0.42.1/proto/cosmos/tx/v1beta1/tx.proto#L47-L64 + + +- `NewAccount(uid, mnemonic, bip39Passwd, hdPath string, algo SignatureAlgo) (Info, error)` 는 + [`bip44 path`](https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki) 기반으로 새 계정을 만들고 이를 디스크에서 유지합니다. + `PrivKey` 는 **절대 암호화되지 않은 상태로 저장되지 않습니다**. 저장되기 전에 + [암호 구문으로 암호화](https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/crypto/armor.go) 됩니다. 이 메서드에서 키 타입과 시퀀스 + 번호는 니모닉에서 개인 및 공용키를 생성하는데 사용되는 BIP44 파생경로의 세그먼트(예: `0`, `1`, `2`, ...) 를 나타냅니다. 같은 니모닉과 파생경로를 + 사용하면, 같은 `PrivKey`, `PubKey` 그리고 `Address` 가 생성됩니다. 키링이 지원하는 키들은 다음과 같습니다. + + +- `secp256k1` + + +- `ed25519` + + +- `ExportPrivKeyArmor(uid, encryptPassphrase string) (armor string, err error)` 에서는 지정된 암호 구문을 사용해 ASCII-아머로 + 암호화된 형식의 개인키를 추출합니다. 그런 다음 `ImportPrivKey(uid, armor, passphrase string)` 함수를 사용하여 Keyring 으로 다시 개인키를 + 가져오거나 `UnarmorDecryptPrivKey(armorStr string, passphrase string)` 함수를 사용하여 원래의 개인키로 복호할 수 있습니다. + +## Next {hide} + +[가스와 수수료](gas-fees.md) 에 대해서 알아보세요. diff --git a/docs/ko/basics/gas-fees.md b/docs/ko/basics/gas-fees.md new file mode 100644 index 000000000..eaa5e52a6 --- /dev/null +++ b/docs/ko/basics/gas-fees.md @@ -0,0 +1,120 @@ + + +# 가스와 수수료 + +이 문서는 Cosmos SDK 애플리케이션 내의 가스와 수수료를 다루는 기본 전략에 대해서 설명합니다. {synopsis} + +### 사전 요구 학습 + +- [SDK 애플리케이션 해부](./app-anatomy.d) {prereq} + +## `Gas` 와 `Fees` 소개 + +Cosmos SDK 에서 `gas` 는 실행에 사용되는 자원 소모량을 추적하는데 사용되는 특별한 단위입니다. `gas` 는 일반적으로 저장소에서 읽고 쓸때마다 소비되고, 비싼 +계산을 해야할 때에도 소비됩니다. 가스는 크게 두 가지 목적이 있습니다. + +- 블록들이 너무 많은 자원을 소비하지 않고 종료되도록 합니다. SDK 에서 [block gas meter](#block-gas-meter) 를 통해 기본형이 구현되어 있습니다. +- 엔드유저의 무분별한 사용이나 스팸을 방지합니다. 이를 위해, `gas` 는 [`message`](../building-modules/messages-and-queries.md#messages) + 실행에는 일반적인 가격이 책정되어 있고, `fee` (`fees = gas * gas-prices`)가 됩니다. `fees` 는 일반적으로 `message` 의 발신자에게 부과됩니다. + SDK 는 기본적으로 `gas` 가격을 강제하지 않고, 다른 방법으로 스팸을 막습니다(예: 대역폭 체계). 그러나 대부분의 애플리케이션이 스팸을 방지하기 위해 `fee` + 메커니즘을 구현합니다. 이는 [`AnteHandler`](#antehandler) 를 통해 수행됩니다. + +## 가스 미터 + +Cosmos SDK 에서, `gas` 는 `uint64` 이며, _gas meter_ 라고 불리는 객체에 의해 관리됩니다. _gas meter_ 는 `Gasmeter` 인터페이스를 구현합니다. + ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/store/types/gas.go#L34-L43 + +where: + +- `GasConsumed()` 는 가스 미터 인스턴스가 소비된 가스의 양을 반환해 줍니다. +- `GasConsumedToLimit()` 는 가스 미터 인스턴스가 소비된 가스의 양을 반환해주거나 제한에 다다랐을 때 그 양을 반환합니다. +- `Limit()` 가스 미터 인스턴스의 제한값을 반환합니다. 가스 미터가 무한이라면 `0` 을 반환합니다. +- `ConsumeGas(amount Gas, descriptor string)` 는 제공된 `gas` 양을 소비합니다. `gas` 가 넘치면, `descriptor` 메시지와 함께 패닉상태가 됩니다. +- `IsPastLimit()` 는 가스 미터 인스턴스가 소비하는 가스의 양이 제한을 초과하면 `true` 를 반환하고, 그렇지 않다면 `false` 를 반환합니다. +- `IsOutOfGas()` 는 가스 미터 인스턴스가 소비하는 가스의 양이 제한과 같거나 초과하면 `true` 를 반환하고, 그렇지 않다면 `false` 를 반환합니다. + +가스 미터는 일반적으로 [`ctx`](../core/context.md) 에 있습니다. 그리고 가스 소비는 다음의 패턴으로 수행됩니다. + +```go +ctx.GasMeter().ConsumeGas(amount, "description") +``` + +기본적으로, Cosmos SDK 는 두가지의 가스미터를 사용하는데, [메인 가스 미터](#메인-가스-미터) 와 [블록 가스 미터](#블록-가스-미터) 입니다. + + +### 메인 가스 미터 + +`ctx.GasMeter()` 는 애플리케이션의 메인 가스 미터입니다. 메인 가스 미터는 `setDeliverState` 를 통해 `BeginBlock` 에서 초기화되며, 그러고 나서 +상태 변경으로 이어지는 실행 시퀀스 동안의 가스 소비량을 추적합니다. 즉, 원래 [`BeginBlock`](../core/baseapp.md#beginblock), +[`DeliverTx`](../core/baseapp.md#delivertx) and [`EndBlock`](../core/baseapp.md#endblock) 에 의해 트리거됩니다. 각 `DeliverTx` +의 시작 시 메인 가스 미터가 `AnteHandler` 에서 __반드시 0으로 설정되어야__ 매 트랜잭션의 가스 소비량을 추적할 수 있습니다. + +가스 소비량은 일반적으로 [`BeginBlocker`, `EndBlocker`](../building-modules/beginblock-endblock.md) 또는 +[`Msg` 서비스](../building-modules/msg-services.md) 에서 모듈 개발자가 수동으로 설정할 수도 있지만, 대부분 저장소에서 읽고 쓸 때마다 자동으로 +처리됩니다. 이 자동 가스 소비 로직은 [`GasKv`](../core/store.md#gaskv-store) 라고 불리는 특별한 저장소에 구현되어 있습니다. + +### 블록 가스 미터 + +`ctx.BlockGasMeter()` 는 블록당 가스 소비량을 추적하고, 일정 한계를 초과하지 않도록 하기위해 사용되는 가스 미터입니다. `BlockGasMeter` 는 +[`BeginBlock`](../core/baseapp.md#beginblock) 이 호출될 때 마다 새 인스턴스가 만들어집니다. `BlockGasMeter` 는 유한하며, 각 블럭의 가스 +한도는 애플리케이션의 합의 매개 변수에서 정의됩니다. 기본적으로 Cosmos SDK 애플리케이션이 사용하는 기본 합의 매개 변수는 Tendermint 가 제공합니다. + ++++ https://github.com/tendermint/tendermint/blob/v0.34.0-rc6/types/params.go#L34-L41 + +새 [트랜잭션](../core/transactions.md) 이 `DeliverTx` 를 통해 처리될 때, `BlockGasMeter` 의 현재 값이 한계인지 체크됩니다. 만약 한계 +값이라면 `DeliverTx` 는 즉시 반환됩니다. `BeginBlock` 자체가 가스를 소비할 수도 있기 때문에, 이는 블록의 첫 번째 트랜잭션에서도 발생할 수 있는 일입니다. +만약 한계 값이 아니라면 트랜잭션은 정상적으로 처리됩니다. `DeliverTx` 의 마지막에, `ctx.BlockGasMeter()` 로 추적되는 가스는 트랜잭션 처리에 소비된 +양만큼 증가됩니다: + +```go +ctx.BlockGasMeter().ConsumeGas( + ctx.GasMeter().GasConsumedToLimit(), + "block gas meter", +) +``` + +## AnteHandler + +`AnteHandler` 는 `CheckTx` 와 `DeliverTx` 동안 모든 트랜잭션에서 수행되는데, 트랜잭션의 각 `sdk.Msg` 에 대한 프로토콜 버퍼 `Msg` 서비스 메서드 +이전에 수행됩니다. `AnterHandler` 는 다음과 같은 형태를 지닙니다. + +```go +// AnteHandler authenticates transactions, before their internal messages are handled. +// If newCtx.IsZero(), ctx is used instead. +type AnteHandler func(ctx Context, tx Tx, simulate bool) (newCtx Context, result Result, abort bool) +``` + +`AnteHandler` 는 SDK 코어가 아니라 모듈에 구현됩니다. 이를 통해 개발자들이 그들의 애플리케이션 필요에 맞는 `AnteHandler` 버전을 선택할 수 있습니다. +그렇긴해도 오늘날 대부분의 애플리케이션들이 [`auth` 모듈](https://github.com/cosmos/cosmos-sdk/tree/master/x/auth) 에 정의된 기본 구현을 +사용합니다. 보통의 Cosmos SDK 애플리케이션에서의 `AnteHandler` 가 수행하는 일들은 다음과 같습니다. + +- 트랜잭션이 올바른 타입인지 검사합니다. 트랜잭션 타입은 `AnteHandler` 를 구현하는 모듈에 정의되어 있으며, 트랜잭션 인터페이스를 따릅니다: + +++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/types/tx_msg.go#L49-L57 + 이를 통해 개발자들는 그들의 애플리케이션 트랜잭션을 위해 다양한 타입을 사용할 수 있습니다. 기본 `auth` 모듈에서 기본 트랜잭션 타입은 `Tx` 입니다: + +++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/proto/cosmos/tx/v1beta1/tx.proto#L12-L25 + +- 트랜잭션에 포함된 각 [`message`](../building-modules/messages-and-queries.md#messages) 의 서명을 검사합니다. 각 `message` 는 한명 + 혹은 여러 발신자에 의해 서명되어야 하며, 이 서명들은 반드시 `AnteHandler` 에 의해 검증되어야 합니다. + +- `CheckTx` 동안, 거래와 함께 제공되는 가스 가격이 로컬 `min-gas-prices` 보다 큰지 검사합니다.(리마인드하자면, 가스 가격은 다음의 등식으로 도출됩니다: + `fees = gas * gas-prices`). `min-gas-prices` 는 각 풀노드의 로컬 매개 변수이며, `CheckTx` 에서 최소 수수료를 제공하지 않은 트랜잭션을 버릴 + 때 사용됩니다. + +- 트랜잭션의 발신자가 수수료 감당할 수 있는 충분한 자금을 보유하고 있는지 검사합니다. 엔드유저가 트랜잭션을 생성하면, 그들은 반드시 다음 3개의 매개 변수 중 2개를 + 알려줘야 합니다(세 번째는 암시적): `fees`, `gas` 그리고 `gas-prices`. 이는 발신자들이 그들의 트랜잭션 실행을 실행하는 노드들을 위해 얼마만큼을 지불할 + 용의가 있는지 알려줍니다. 제공된 `gas` 값은 `GasWanted` 라는 매개 변수로 저장되고 나중에 사용됩니다. + +- `newCtx.gasMeter` 를 0으로 설정하고 ,`GasWanted` 를 한도로 둡니다. __이 단계는 매우 중요한데,__ 트랜잭션이 가스를 무한으로 소비하지 못하도록 할 + 뿐만 아니라, `ctx.GasMeter` 가 각 `DeliverTx` 사이에서 재설정 되도록 합니다.(`ctx` 는 `Antehandler` 가 실행된 후 `newCtx` 로 설정되며, + `AnteHandler` 는 `DeliverTx` 가 호출될 때 마다 수행됩니다.) + +위에서 설명한 바와 같이, `AnteHandler` 는 트랜잭션 실행에 소비할 수 있는 가스의 최대 한도인 `GasWanted` 를 반환합니다. 최종적으로 실제 소비량은 +`GasUsed` 로 표시되고, 반드시 `GasUsed =< GasWanted` 여야 합니다. `GasWanted` 와 `GasUsed` 모두 +[`DeliverTx`](../core/baseapp.md#delivertx) 가 리턴될 때 합의 엔진으로 전달됩니다. + +## Next {hide} + +[baseapp](../core/baseapp.md) 에 대해서 알아보세요 {hide} diff --git a/docs/ko/core/README.md b/docs/ko/core/README.md new file mode 100644 index 000000000..eeacad118 --- /dev/null +++ b/docs/ko/core/README.md @@ -0,0 +1,27 @@ + + +# Core Concepts + +여기는 Cosmos SDK 의 핵심 개념들에 대한 참고 문서를 포함하고 있습니다. + +1. [`BaseApp`](./baseapp.md) +2. [Transaction](./transactions.md) +3. [Context](./context.md) +4. [Node Client](./node.md) +5. [Store](./store.md) +6. [Encoding](./encoding.md) +7. [gRPC, REST and Tendermint Endpoints](./grpc_rest.md) +8. [Command-Line Interface](./cli.md) +9. [Events](./events.md) +10. [Telemetry](./telemetry.md) +11. [Object-Capabilities](./ocap.md) +12. [RunTx recovery middleware](./runtx_middleware.md) +13. [Simulation](./simulation.md) +14. [Protobuf documentation](./proto-docs.md) +15. [In-Place Store Migrations](./upgrade.md) + +핵심 개념들에 대해 읽은 후, [IBC 문서](../ibc/README.md) 에서 IBC 핵심 개념과 애플리케이션에서 어떻게 IBC 를 통합하는지 알아보세요. diff --git a/docs/ko/core/baseapp.md b/docs/ko/core/baseapp.md new file mode 100644 index 000000000..7ffa1f001 --- /dev/null +++ b/docs/ko/core/baseapp.md @@ -0,0 +1,448 @@ + + +# BaseApp + +이 문서는 SDK 애플리케이션의 코어 기능들을 구현하는 추상화인 `BaseApp` 을 설명합니다. {synopsis} + +## 사전 요구 학습 + +- [SDK 애플리케이션 해부](../basics/app-anatomy.md) {prereq} +- [SDK 트랜잭션 생명주기](../basics/tx-lifecycle.md) {prereq} + +## 소개 + +`BaseApp` 은 이름대로 SDK 애플리케이션의 코어를 구현하는 기본 타입입니다: + +- 상태 기계와 기반 합의 엔진(예: Tendermint) 이 상호작용하기 위한 [애플리케이션 블록체인 인터페이스](#abci) +- 메시지와 쿼리를 적절한 모듈로 라우팅하기 위한 [서비스 라우터](#서비스-라우터-(service-routers)) +- 수신된 ABCI 메시지에 근거하여 상태 기계가 다른 휘발성 상태를 가질 수 있도록 하는 다른 [상태들](#상태들(states)), + +`BaseApp` 의 목적은 SDK 애플리케이션에 필수 레이어를 제공함으로써 개발자들이 자신의 커스텀 애플리케이션을 쉽게 확장할 수 있도록 하는 것입니다. 일반적으로 +개발자들은 자신의 애플리케이션을 위해 아래와 같은 커스텀 타입을 만들 것 입니다. + +```go +type App struct { + // reference to a BaseApp + *baseapp.BaseApp + + // list of application store keys + + // list of application keepers + + // module manager +} +``` + +`BaseApp` 으로 애플리케이션을 확장하면 `BaseApp` 의 모든 메서드에 접근할 수 있습니다. 이를 통해 개발자는 그들의 커스텀 애플리케이션을 원하는 모듈로 구성할 수 +있고, ABCI와 서비스 라우터, 상태 관리 로직을 구현하는 힘든 일에 신경쓰지 않아도 됩니다. + +## 타입 정의 (Type Definition) + +`BaseApp` 타입은 Cosmos SDK 기반 애플리케이션에 중요한 매개 변수를 많이 가지고 있습니다. + ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/baseapp/baseapp.go#L46-L131 + +제일 중요한 요소들을 살펴봅시다. + +> **Note**: 모든 매개 변수들을 설명하지 않으며, 제일 중요한 것들만 다룹니다. 타입 정의 전체 목록을 참고하세요. + +먼저, 애플리케이션 부트스트랩 동안 초기화되는 중요 매개 변수들입니다. + +- [`CommitMultiStore`](./store.md#commitmultistore) : 애플리케이션의 메인 저장소로써 [각 블록의 마지막](#commit) 에 커밋되는 표준 상태를 + 유지합니다. 이 저장소는 **캐시되지 않으며**, 이는 애플리케이션의 휘발성 상태 (커밋되지 않은) 를 업데이트하는데 사용되지 않습니다. 애플리케이션의 각 모듈은 + 멀티 저장소에 있는 `KVStores` 를 사용하여 해당 상태의 서브셋을 유지합니다. + +- 데이터베이스: `db` 는 `CommitMultiStore` 가 데이터 유지를 위해 사용합니다. + +- [메시지 서비스 라우터](#메시지-서비스-라우터-(Msg-service-router)): `msgServiceRouter` 는 해당 `Msg` 서비스 모듈로 `sdk.Msg` 요청의 + 라우팅을 가능케 합니다. 여기서 `sdk.Msg` 는 애플리케이션과 기반 합의 엔진 간의 인터페이스를 구현하는 ABCI 메시지가 아니라 애플리케이션 상태 업데이트를 하기 + 위해 서비스가 처리해야 하는 트랜잭션 구성요소를 의미합니다. + +- [gRPC 쿼리 라우터](#grpc-쿼리-라우터-(grpc-query-router)): `grpcQueryRouter` 는 gRPC 쿼리를 처리하기 위해 해당 모듈로 라우팅합니다. 이 + 쿼리들은 ABCI 메시지 자체는 아니지만, 관련 모듈의 gRPC `Query` 서비스로 전달됩니다. + +- [`TxDecoder`](https://godoc.org/github.com/cosmos/cosmos-sdk/types#TxDecoder): Tendermint 엔진이 전달한 로우 트랜잭션 바이트를 + 디코드하는데 사용됩니다. + +- [`ParamStore`](#paramstore): 어플리케이션 합의 매개 변수를 get, set 할 때 사용됩니다. + +- [`AnteHandler`](#antehandler): 이 핸들러는 트랜잭션이 수신되었을 때 서명 검증, 수수료 지불, 기타 사전 메시지 실행 확인에 사용됩니다. + 이는 [`CheckTx/RecheckTx`](#checktx) 와 [`DeliverTx`](#delivertx) 중에 실행됩니다. + +- [`InitChainer`](../basics/app-anatomy.md#initchainer), + [`BeginBlocker` and `EndBlocker`](../basics/app-anatomy.md#beginblocker-and-endblocker): 애플리케이션이 Tendermint + 엔진이 보낸 `InitChain`, `BeginBlock` 와 `EndBlock` ABCI 메시지를 수신하면 실행되는 기능들입니다. + + +그리고, [휘발성 상태](#휘발성-상태-(volatile-states)) (예: 캐시 상태) 를 정의하는데 사용되는 매개변수들 입니다: + +- `checkState`: 이 상태는 [`CheckTx`](#checktx) 동안 업데이트되고 [`Commit`](#commit) 시 재설정됩니다. +- `deliverState`: 이 상태는 [`DeliverTx`](#delivertx) 동안 업데이트되고 [`Commit`](#commit) 시 `nil` 로 설정되며, `BeginBlock` + 에서 다시 초기화됩니다. + +마지막으로, 더 중요한 몇 가지 매개 변수들입니다: + +- `voteInfos`: 이 매개 변수는 투표하지 않았거나, 제안자가 표를 포함하지 않아서 precommit 이 누락된 검증자들의 목록을 포함합니다. 이 정보는 + [Context](#context) 가 가지고 있고, 애플리케이션이 부재 검증자 징계같은 다양한 곳에 사용할 수 있습니다. + +- `minGasPrices`: 이 매개 변수는 노드에서 허용되는 최소 가스 가격을 정의합니다. 이는 **로컬** 매개 변수이며, 모든 노드가 각각 다른 `minGasPrices` 를 + 설정할 수 있음을 의미합니다. 주로 스팸 방지 메커니즘으로 [`CheckTx`](#checktx) 동안 `AnteHandler` 에서 사용됩니다. 트랜잭션이 + [메모리 풀](https://tendermint.com/docs/tendermint-core/mempool.html#transaction-ordering) 에 들어가려면 트랜잭션 가스 가격이 + `minGasPrices` 의 최소 가스 가격 중 하나보다 커야합니다. (예: `minGasPrices == 1uatom,1photon` 일 때, 트랜잭션의 `gas-price` 는 + `1uatom` 이나 `1photon` 보다 반드시 커야합니다.) + +- `appVersion`: 애플리케이션의 버전. [애플리케이션 생성자 함수](../basics/app-anatomy.md#constructor-function) 에서 설정됩니다. + +## 생성자 + +```go +func NewBaseApp( + name string, logger log.Logger, db dbm.DB, txDecoder sdk.TxDecoder, options ...func(*BaseApp), +) *BaseApp { + + // ... +} +``` + +`BaseApp` 생성자 함수는 아주 간단합니다. 유일하게 주목할 만한건 `BaseApp` 에 추가적인 +[`options`](https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/baseapp/options.go) 를 제공해 순차적으로 실행할 수 있다는 것 +입니다. `options` 는 일반적으로 중요 매개 변수들을 위한 `setter` 함수들인데, 가지치기 옵션을 설정하는 `SetPruning()` 이나 노드의 +`min-gas-prices` 를 설정하는 `SetMinGasPrices()` 같은 것들입니다. + +개발자는 그들의 애플리케이션 필요에 따라 추가적인 `options` 를 추가할 수 있습니다. + +## 상태 업데이트 + +`BaseApp` 은 두 가지 주요 휘발성 상태와 루트 또는 메인 상태를 유지합니다. 메인 상태는 애플리케이션의 표준 상태이며, 휘발성 상태인 `checkState` 와 +`deliverState` 는 [`Commit`](#commit) 중에 메인 상태 사이에서 상태 전환을 처리하는데 사용됩니다. + +내부적으로는 메인 또는 루트 상태인 `CommitMultiStore` 만 존재합니다. +이 루트 상태를 통해, 우리는 _저장소 분기 (store branching,_ `CacheWrap` 함수가 수행) 라고 불리는 메커니즘을 사용해 두 가지 휘발성 상태를 파생합니다. + +타입들은 다음과 같이 묘사될 수 있습니다. + +![Types](baseapp_state_types.png) + +### InitChain 상태 업데이트 + +`InitChain` 동안, 두 가지 휘발성 상태인 `checkState` 와 `deliverState` 는 루트 `CommitMultiStore` 분기에 의해 설정됩니다. 이후의 읽기, +쓰기는 `CommitMultiStore` 의 분기된 버전에서 발생합니다. 메인 상태로의 불필요한 동작을 피하기 위해, 분기된 저장소의 모든 읽는 동작은 캐시됩니다. + +![InitChain](baseapp_state-initchain.png) + +### CheckTx 상태 업데이트 + +`CheckTx` 동안, 루트 저장소에서 마지막으로 커밋 상태를 기반으로 하는 `checkState` 는 모든 읽기 쓰기 동작에서 사용됩니다. 여기서는 `AnteHandler` 만 +실행하고 트랜잭션의 모든 메시지에 대해 서비스 라우터가 존재하는지 검사합니다. `AnteHandler` 가 실행할 때, 이미 분기된 `checkState` 를 분기한다는 것에 +주의하세요. 만약 `AnteHandler` 가 실패하면, 상태 전이가 `checkState` 에 반영되지 않습니다. 즉, `checkState` 는 성공 시에만 업데이트됩니다. + +![CheckTx](baseapp_state-checktx.png) + +### BeginBlock 상태 업데이트 + +`BeginBlock` 동안, `deliverState` 는 이어지는 `DeliverTx` ABCI 메시지에서 사용하기 위해 설정됩니다. `deliverState` 는 루트 저장소의 마지막 +커밋 상태를 기반으로 하고 분기됩니다. `deliverState` 는 [`Commit`](#commit) 할 때 `nil` 로 설정됩니다. + +![BeginBlock](baseapp_state-begin_block.png) + +### DeliverTx 상태 업데이트 + +`DeliverTx` 의 상태 흐름은 상태 전이가 `deliverState` 에 발생하고, 트랜잭션 메시지가 실행된다는 점을 제외하면 `CheckTx` 와 거의 동일합니다. +`CheckTx` 와 유사하게, 상태 전이는 이중 분기 상태 -- `deliverState` 에서 발생합니다. 메시지 실행이 성공하면 결과는 `deliverState` 에 커밋됩니다. +만약 메시지 실행이 실패하면, `AnteHandler` 의 상태 전이가 유지됩니다. + +![DeliverTx](baseapp_state-deliver_tx.png) + +### Commit 상태 업데이트 + +`Commit` 동안 `deliverState` 에서 발생한 모든 상태 전이는 최종적으로 루트 `CommitMultiStore` 에 쓰여지고, 디스크에 커밋되며 새로운 애플리케이션 +루트 해시가 됩니다. 이 상태 전이는 이제 최종적인 것으로 간주됩니다. 마지막으로, `checkState` 는 새롭게 커밋된 상태로 설정되고 `deliverState` 는 +`nil` 로 설정되어 `BeginBlock` 에서 재설정됩니다. + +![Commit](baseapp_state-commit.png) + +## ParamStore + +`InitChain` 동안, `RequestInitChain` 은 `ConsensusParams` 를 제공합니다. `ConsensusParams` 는 증거 매개 변수 외에 최대 가스, 크기 등 블록 +실행과 관련된 매개 변수를 포함합니다. 이 매개 변수들은 nil 이 아닌 경우, `BaseApp` 의 `ParamStore` 에 설정됩니다. `ParamStore` 는 실제로는 +`x/params` 모듈 `Subspace` 에 의해 관리됩니다. 이로 인해 온체인(on-chain) 거버넌스를 통하여 매개 변수를 조정할 수 있습니다. + +## 서비스 라우터 (Service Routers) + +애플리케이션이 메시지와 쿼리를 수신할 때, 반드시 적절한 모듈로 라우팅해서 처리되게 해야 합니다. 라우팅은 `BaseApp` 의 메시지를 위한 `msgServiceRouter` 와 +쿼리를 위한 `grpcQueryRouter` 를 통해 수행됩니다. + +### 메시지 서비스 라우터 (`Msg` Service Router) + +[`sdk.Msg`s](#../building-modules/messages-and-queries.md#messages) 는`CheckTx` 와 `DeliverTx` ABCI 메시지를 통해 Tendermint +엔진에서 보내진 트랜잭션에서 추출된 후 라우팅해야 합니다. 이를 위해 `BaseApp` 은 정규화된 서비스 메서드 (`string`, 각 모듈의 Protobuf `Msg` 서비스에 +정의된) 를 적절한 모듈의 `MsgServer` 구현에 매핑하는 `msgServiceRouter` 를 가지고 있습니다. + +[`BaseApp` 에 포함된 기본 `msgServiceRouter`](https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/baseapp/msg_service_router.go) 는 +상태가 없습니다. 그러나 일부 애플리케이션은 거버넌스가 특정 라우트를 비활성화 하거나 업그레이드 목적의 새로운 모듈을 가리키도록 허용하는 것과 같이 상태가 있는 라우팅 +메커니즘의 사용을 원할 수 도 있습니다. 이러한 이유 때문에 `sdk.Context` 도 [`msgServiceRouter` 내 각각의 라우트 핸들러](https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/baseapp/msg_service_router.go#L31-L32) 로 전달됩니다. +상태가 없는 라우터의 경우에는 `ctx` 를 무시해도 됩니다. + +애플리케이션의 `msgServiceRouter` 는 [애플리케이션 생성자](../basics/app-anatomy.md#app-constructor) 에서 모든 애플리케이션 모듈로 초기화되는 +애플리케이션 [모듈 관리자](../building-modules/module-manager.md#manager) 를 사용하여 모든 라우트로 초기화 됩니다. (`RegisterService` +메서드를 통해) + +### gRPC 쿼리 라우터 + +`sdk.Msg` 와 유사하게, [`queries`](../building-modules/messages-and-queries.md#queries) 는 적절한 모듈의 +[`Query` 서비스](../building-modules/query-services.md) 로 전달되어야 합니다. 이를 위해, `BaseApp` 에서는 정규화된 서비스 메서드 (`string` +, 그들의 Protobuf `Query` gRPC 에 정의된) 를 그들의 `QueryServer` 구현에 매핑하는 `grpcQueryRouter` 를 가지고 있습니다. +`grpcQueryRouter` 는 쿼리 처리 초반 단계에서 호출되는데, gRPC 엔드포인트로 gRPC 쿼리를 바로 보내거나 Tendermint 엔드포인트의 +[`Query` ABCI 메시지](#쿼리-(query)) 를 통할 수 있습니다. + +`msgServiceRouter` 와 마찬가지로, `grpcQueryRouter` 는 [애플리케이션 생성자](../basics/app-anatomy.md#app-constructor) 에서 모든 +애플리케이션 모듈로 초기화되는 애플리케이션 [모듈 관리자](../building-modules/module-manager.md#manager) 를 사용하여 모든 쿼리 라우트로 초기화 +됩니다. (`RegisterService` 메서드를 통해) + +## 메인 ABCI 메시지들 + +[어플리케이션 블록체인 인터페이스](https://tendermint.com/docs/spec/abci/) (Application-Blockchain Interface, ABCI) 는 상태 기계를 +합의 엔진과 연결하여 기능적 풀노드를 형성하는 일반적인 인터페이스입니다. 모든 언어로 래핑할 수 있으며, Tendermint 와 같은 ABCI 호환이 가능한 합의 엔진 위에 +구축된 각각의 애플리케이션별 전용 블록체인에 의해 구현되어야 합니다. + +합의 엔진은 두 가지 중요한 일을 처리합니다 + +- 네트워크 로직. 주로 블록 파트, 거래, 합의 투표를 퍼트리는 일을 합니다. +- 합의 로직. 블록의 형태로 트랜잭션들을 결정론적 순서로 만드는 일을 합니다. + +트랜잭션의 유효성과 상태를 정의하는 일은 합의 엔진의 역할이 **아닙니다.** 일반적으로 트랜잭션은 합의 엔진이 `[]bytes` 형태로 처리하며, ABCI 를 통해서 +애플리케이션에 전달되어 디코드되고 처리됩니다. 네트워크와 합의 처리의 중요한 부분 (예: 블록 시작, 블록 커밋, 확인되지 않은 트랜잭션 수신 등) 에서 합의 엔진은 +상태 기계가 작동하도록 ABCI 메시지를 전달합니다. + +Cosmos SDK 를 기반으로 하는 개발자들은 `BaseApp` 에 인터페이스가 내장되어 있기 때문에 ABCI 를 직접 구현할 필요가 없습니다. `BaseApp` 에서 구현하는 +주요 ABCI 메시지인 `CheckTx` 와 `DeliverTx` 를 살펴보겠습니다. + +### CheckTx + +`CheckTx` 는 확인되지 않은(즉, 아직 유효 블록에 포함되지 않은) 새로운 트랜잭션이 풀노드에서 수신될 때 합의 엔진에서 전송됩니다. `CheckTx` 의 역할은 +스팸 트랜잭션들로부터 풀노드의 메모리 풀 (확인되지 않은 트랜잭션이 블록에 포함되기 전까지 저장되는 곳) 을 보호하는 역할을 합니다. 확인되지 않은 트랜잭션들은 +`CheckTx` 를 통과한 경우에만 피어들에게 전달됩니다. + +`CheckTx()` 는 _stateful_ 과 _stateless_ 확인 모두 수행할 수 있으나, 개발자들은 이를 가볍게 만들기 위해 노력해야 합니다. Cosmos SDK 에서는 +[트랜잭션을 디코딩](./encoding.md) 한 후 `CheckTx()` 가 다음을 확인하도록 구현되어 있습니다. + +1. 트랜잭션에서 `sdk.Msg` 를 추출합니다. +2. 각 `sdk.Msg` 의 `ValidateBasic()` 을 호출하여 _stateless_ 검사를 수행합니다. _stateless_ 검사가 _stateful_ 검사보다 계산 비용이 낮기 + 때문에 이를 먼저 수행합니다. 만약 `ValidateBasic()` 이 실패하면, `CheckTx` 는 _stateful_ 검사를 진행하기 전에 반환되어서 자원을 절약합니다. +3. [계정](../basics/accounts.md) 의 비모듈과 관련있는 _stateful_ 검사를 수행합니다. 이 단계는 `sdk.Msg` 서명이 유효한지, 제공된 수수료는 + 충분한지, 발신자 계정이 지불하기로 한 수수료를 지불할 충분한 자금이 있는지를 주로 검사합니다. 여기서 `sdk.Msg` 가 처리되는 것은 아니므로, 정확한 + [`gas`](../basics/gas-fees.md) 가 계산되지 않습니다. 일반적으로, [`AnteHandler`](../basics/gas-fees.md#antehandler) 는 가스를 + 0으로 보내는 트랜잭션 스팸을 방지하기 위해, 트랜잭션에 제공된 `gas` 가 로우 트랜잭션 크기에 맞는 최소 가스 기준 보다 큰지 확인합니다. +4. 각 `sdk.Msg` 의 정규화된 서비스 메서드가 `msgServiceRouter` 내의 라우트와 일치하는지 확인해야 하지만, 실제로 `sdk.Msg` 를 처리하지는 않습니다. + `sdk.Msg` 는 오직 표준 상태가 업데이트 되어야할 때에 처리되어야 하며, 이는 `DeliverTx` 에서 일어납니다. + +두 번째와 세 번째 단계는 `CheckTx()` 가 `runTxModeCheck` 모드로 호출하는 `RunTx()` 함수 내의 `AnteHandler` 에 의해 수행됩니다. +`CheckTx()` 의 각 단계 동안, `checkState` 라는 특수한 [휘발성 상태](#휘발성-상태-(volatile-states)) 가 업데이트 됩니다. 이 상태는 +[표준 메인 상태](#main-state) 를 수정하지 않고 각 트랜잭션의 CheckTx() 호출에 의해 트리거되어 임시 변화를 계속 추적하는데에 사용됩니다. 예를 들어, +트랜잭션이 `CheckTx()` 를 거칠 때, 트랜잭션 수수료는 `checkState` 내의 발신자 계정에서 공제됩니다. 첫 번째 트랜잭션이 처리되기 전에 만약 두 번째 +트랜잭션을 같은 계정으로부터 수신하고, 첫 번째 거래 중 `checkState` 에서 모든 자금을 소비했다면, 두 번째 트랜잭션은 `CheckTx()` 가 실패하고 거부될 +것입니다. 어떠한 경우라도 발신자의 계정은 트랜잭션이 실제로 블록에 포함되기 전까지는 수수료가 지불되지 않을 것입니다. 왜냐하면 `checkState` 는 절대로 메인 +상태를 커밋하지 않기 때문입니다. `checkState` 는 블록이 [커밋](#commit) 될 때마다 메인 상태의 최신 상태로 재설정 됩니다. + +`CheckTx` 는 [`abci.ResponseCheckTx`](https://tendermint.com/docs/spec/abci/abci.html#messages) 타입의 합의 엔진에 대한 응답을 +반환합니다. 응답은 다음 항목들을 포함합니다: + +- `Code (uint32)`: 응답 코드. 성공일 때 `0` +- `Data ([]byte)`: 결과 바이트.(있는 경우) +- `Log (string):` 애플리케이션 로그. 비결정적일 수 있습니다. +- `Info (string):` 추가 정보. 비결정적일 수 있습니다. +- `GasWanted (int64)`: 트랜잭션을 위해 요청한 가스입니다. 사용자가 트랜잭션을 생성할 때 제공합니다. +- `GasUsed (int64)`: 트랜잭션에 의해 소비된 가스입니다. `CheckTx` 동안 이 값은 로우 트랜잭션의 크기와 트랜잭션 바이트의 표준 가격을 곱하여 계산됩니다. + 예시: + +++ https://github.com/cosmos/cosmos-sdk/blob/7d7821b9af132b0f6131640195326aa02b6751db/x/auth/ante/basic.go#L104-L105 +- `Events ([]cmn.KVPair)`: 트랜잭션 인덱싱과 필터링을 위한 키값 태그. 자세한 내용은 [`event`s](./events.md) 를 참고하세요. +- `Codespace (string)`: 코드의 네임스페이스. + + +#### RecheckTx + +`Commit` 이후, 블록에 포함된 트랜잭션을 제외한 후 노드의 로컬 메모리 풀에 남아있는 트랜잭션들에 대해 `CheckTx` 가 다시 실행됩니다. 블록이 커밋될 때마다 +모든 트랜잭션에 대해서 재검사하는 것을 막기 위해, 설정 옵션 `mempool.recheck=false` 를 설정할 수 있습니다. Tendermint v0.32.1 부터 들어오는 +트랜잭션이 새로운 (`ChecekTxType_New`) 인지 재검사하는 (`CheckTxType_Recheck`) 인지를 나타내는 `Type` 매개 변수를 `CheckTx` 함수가 사용할 수 +있습니다. 이로 인해 `CheckTxType_Recheck` 중에 서명 검증과 같은 특정한 검사를 건너뛸 수 있습니다. + +### DeliverTx + +합의 엔진이 블록 제안을 받으면, 블록의 각 트랜잭션은 애플리케이션이 처리해야 합니다. 이를 위해 합의 엔진은 각 트랜잭션에 대한 애플리케이션에게 `DeliverTx` +메시지를 순차적으로 보냅니다. + +어떤 블록의 첫 번째 트랜잭션이 처리되기 전에, [휘발성 상태](#휘발성-상태-(volatile-states)) 인 `deliverState` 가 +[`BeginBlock`](#beginblock) 중에 초기화됩니다. 이 상태는 `DeliverTx` 를 통해 트랜잭션이 처리될 때마다 업데이트되며, `nil` 로 설정된 이후에 블록이 +[커밋](#commit) 되면 [메인 상태](#메인-상태-(main-state)) 에 커밋됩니다. + +`DeliverTx` 는 **`CheckTx` 와 정확히 동일한 단계**를 수행하는데, 세 번째 단계에서 약간 주의해야하고 다섯 번째 단계가 추가되었습니다: + +1. `AnteHandler` 는 트랜잭션의 `gas-prices` 가 유효한지 체크하지 **않습니다.** 이는 `gas-prices` 와 비교하는 `min-gas-prices` 값이 노드 + 로컬 값이기 때문에, 한 노드에서는 충분해도 풀노드에서는 그렇지 않을 수 있습니다. 이것은 제안자가 무료 트랜잭션을 잠재적으로 포함할 수 있다는 뜻인데, + 이는 비록 제안자들이 인센티브를 받지 않더라도 그들이 제안한 블록에 대한 수수료를 얻을 수 있기 때문입니다. + +2. 트랜잭션 내의 각 `sdk.Msg` 에 대해, 알맞은 모듈의 Protobuf [`Msg` 서비스](../building-modules/msg-services.md) 로 라우팅합니다. + _stateful_ 검사가 추가로 수행되고, 모듈의 `keeper` 에 의해 `deliverState` 의 `context` 에 있는 분기된 멀티 저장소가 업데이트됩니다. 만약 + `Msg` 서비스가 성공적으로 반환되면, `context` 의 분기된 멀티 저장소는 `deliverState` `CacheMultiStore` 에 쓰여집니다. + +(2) 에 설명된 다섯 번째 추가단계 중, `GasConsumed` 의 값은 저장소에 읽기/쓰기를 할 때마다 증가됩니다. 각 작업의 기본 비용을 여기서 확인할 수 있습니다: + ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/store/types/gas.go#L164-L175 + +어느 시점에서라도 `GasConsumed > GasWanted` 인 경우, 함수는 `Code != 0` 과 `DeliverTx` 실패를 반환합니다. + +`DeliverTx` 는 [`abci.ResponseDeliverTx`](https://tendermint.com/docs/spec/abci/abci.html#delivertx) 타입의 합의 엔진에 대한 +응답을 반환합니다. + +- `Code (uint32)`: 응답 코드. 성공일 때 `0` +- `Data ([]byte)`: 결과 바이트.(있는 경우) +- `Log (string):` 애플리케이션 로그. 비결정적일 수 있습니다. +- `Info (string):` 추가 정보. 비결정적일 수 있습니다. +- `GasWanted (int64)`: 트랜잭션을 위해 요청한 가스입니다. 사용자가 트랜잭션을 생성할 때 제공합니다. +- `GasUsed (int64)`: 트랜잭션에 의해 소비된 가스입니다. `DeliverTx` 동안 이 값은 로우 트랜잭션의 크기와 트랜잭션 바이트의 표준 가격을 곱하고, 저장소에 + 읽기/쓰기가 발생할 때마다 가스를 추가하여 계산됩니다. +- `Events ([]cmn.KVPair)`: 트랜잭션 인덱싱과 필터링을 위한 키값 태그(예: 계정별). 자세한 내용은 [`event`s](./events.md) 를 참고하세요. +- `Codespace (string)`: 코드의 네임스페이스. + +## RunTx, AnteHandler 와 RunMsgs + +### RunTx + +`RunTx` 는 `CheckTx`/`DeliverTx` 에서 호출되어서 트랜잭션을 처리하며, `runTxModeCheck` 또는 `runTxModeDeliver` 를 매개 변수로 사용해서 두 +실행 모드를 구분합니다. `RunTx` 는 이미 디코드된 트랜잭션을 받습니다. + +`RunTx` 가 호출되면 적절한 모드 (`runTxModeCheck` 또는 `runTxModeDeliver`) 로 `getContextForTx()` 를 호출하여 `context` 의 +`CacheMultiStore` 를 검색합니다. 이 `CacheMultiStore` 는 메인 저장소의 분기이며, 캐시 기능 (쿼리 요청을 위한) 이 있으며, `DeliverTx` 의 +`BeginBlock` 중, 그리고 `CheckTx` 에 대한 이전 블록의 `Commit` 중에 인스턴스화 됩니다. 그 후, 두 `defer func()` 가 +[`gas`](../basics/gas-fees.md) 관리를 위해 호출됩니다. 그 함수들은 `runTx` 반환 때 수행되고 `gas` 가 실제로 소비되었는지 확인하며, 오류가 발생했을 +경우 오류를 던집니다. + +그 이후, `RunTx()` 는 `Tx` 의 각 `sdk.Msg` 에 대해 `ValidateBasic()` 을 호출하여 예비 _stateless_ 유효성 검사를 수행합니다. 어떠한 경우라도 +`sdk.Msg` 가 `ValidateBasic()` 을 통과하지 못하고 실패하면, `RunTx()` 는 에러를 반환합니다. + +그러고나서, 애플리케이션의 [`AnteHandler`](#antehandler) 이 수행됩니다 (있으면). 이 단계의 준비로, `checkState`/`deliverState` 의 +`context` 그리고 `context` 의 `CacheMultiStore` 는 `cacheTxContext()` 함수를 사용하여 분기됩니다. + ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/baseapp/baseapp.go#L623-L630 + +이렇게 하면 `RunTx` 가 실패할 경우 `AnteHandler` 실행 중에 만들어진 상태 변경이 커밋되지 않도록 할 수 있습니다. 또한 `anteHandler` 를 구현하는 모듈이 +Cosmos SDK 의 [오브젝트 자격 (Object-Capabilities)](./ocap.md) 의 중요한 부분인 상태 저장하는 것을 방지합니다. + +마지막으로, [`RunMsgs()`](#runmsgs) 함수는 `Tx` 의 `sdk.Msg` 들의 처리를 위해 호출됩니다. 이 단계의 준비로 `CacheMultiStore` 는 +`cacheTxContext()` 함수를 사용해서 분기됩니다. + +### AnteHandler + +`AnteHandler` 는 `AnteHandler` 인터페이스를 구현하는 특별한 핸들러이며 트랜잭션의 내부 메시지가 처리되기 전에 트랜잭션을 인증하는데 사용됩니다. + ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/types/handler.go#L6-L8 + +`AnteHandler` 는 이론적으로는 선택사항이지만, 그러나 블록체인 네트워크에서 여전히 중요한 구성 요소입니다. 세 가지 주요 용도로 사용됩니다. + +- 스팸에 대한 1차 방어선, 수수료 공제와 [`sequence`](./transactions.md#transaction-generation) 확인으로 트랜잭션에 대한 2차 방어선 (1차는 + 메모리 풀) 이 됩니다. +- 예비 _stateful_ 유효성 검사를 수행해서 서명이 유효한지 발신자가 수수료를 지불할 충분한 자금이 있는지 등을 확인합니다. +- 트랜잭션 수수료 수금으로 이해관계자의 인센티브화 하는 역할을 합니다. + +`BaseApp` 은 `AnteHandler` 를 매개 변수로 가지고 있으며, 이는 [애플리케이션 생성자](../basics/app-anatomy.md#application-constructor) +에서 초기화됩니다. 가장 널리 사용되는 `AnteHandler` 는 +[`auth` 모듈](https://github.com/cosmos/cosmos-sdk/blob/v0.42.1/x/auth/ante/ante.go) 입니다. + +`AnteHandler` 에 대한 더 많은 정보는 [여기](../basics/gas-fees.md#antehandler) 를 클릭하세요. + +### RunMsgs + +`RunMsgs` 는 `RunTx` 에서 `runTxModeCheck` 를 매개변수로 사용하여 트랜잭션의 각 메시지에 대한 라우트가 있는지 확인하고, `runTxModeDeliver` 를 +사용하여 `sdk.Msg` 를 실제로 처리합니다. + +먼저 `sdk.Msg` 를 나타내는 Protobuf `Any` 의 `type_url` 을 확인하여 `sdk.Msg` 의 정규화된 타입 이름을 검색합니다. 그리고나서 애플리케이션의 +[`msgServiceRouter`](#msg-service-router) 를 사용해서 `type_rul` 와 관련된 `Msg` 서비스가 있는지 확인합니다. 여기서 만약 +`mode == runTxMOdeCheck` 라면 `RunMsgs` 를 반환합니다. 그렇지 않고 `mode == runTxModeDeliver` 라면 `RunMsgs` 가 반환되기 전에, +[`Msg` 서비스](../building-modules/msg-services.md) RPC 가 수행됩니다. + +## 다른 ABCI 메시지들 + +### InitChain + +[`InitChain` ABCI message](https://tendermint.com/docs/app-dev/abci-spec.html#initchain) 는 체인이 처음 시작될 때 Tendermint +엔진에서 전달됩니다. 이것은 주로 다음과 같은 매개 변수와 상태를 **초기화** 하는데 사용됩니다. + +- `setConsensusParams` 를 통한 [합의 매개 변수](https://tendermint.com/docs/spec/abci/apps.html#consensus-parameters) 초기화. +- `setCheckState` 와 `setDeliverState` 를 통해 [`checkState` 와 `deliverState`](#휘발성-상태-(volatile-states))초기화. +- 제네시스 트랜잭션들을 처리하기 위해 [블록 가스 미터](../basics/gas-fees.md#block-gas-meter) 를 무한 가스로 초기화. + +마지막으로, `BaseApp`의 `InitChain(req abci.RequestInitChain)` 매서드는 애플리케이션의 +[`initChainer()`](../basics/app-anatomy.md#initchainer) 을 호출하는데, 이를 통해서 애플리케이션의 메인 상태를 초기화 합니다. 이 때, +`genesis file` 과, 정의되어 있다면 각 애플리케이션 모듈의 [`InitGenesis`](../building-modules/genesis.md#initgenesis) 함수가 +사용됩니다. + +### BeginBlock + +[`BeginBlock` ABCI 메시지](#https://tendermint.com/docs/app-dev/abci-spec.html#beginblock) 는 블록의 각 트랜잭션에 대해 +`DeliverTx` 가 수신되기 전에 Tendermint 엔진이 올바른 제안자가 생성한 블록 제안을 수신하면 Tendermint 엔진에 의해서 보내집니다. 이를 통해 개발자는 각 +블록의 시작 부분에서 로직을 실행할 수 있습니다. Cosmos SDK 에서 `BeginBlock(req abci.RequestBeginBlock)` 메서드는 다음을 따릅니다: + +- `setDeliver` 을 통해 매개 변수로 전달된 `req abci.RequestBeginBlock` 를 사용한 마지막 헤더로 + [`deliverState`](#휘발성-상태-(volatile-states)) 를 초기화합니다. + +++ https://github.com/cosmos/cosmos-sdk/blob/7d7821b9af132b0f6131640195326aa02b6751db/baseapp/baseapp.go#L387-L397 + 이 함수는 또한 [메인 가스 미터](../basics/gas-fees.md#main-gas-meter) 를 초기화합니다. +- `maxGas` 한도로 [블록 가스 미터](../basics/gas-fees.md#block-gas-meter) 를 초기화합니다. 블록 내의 `gas` 소비는 `maxGas` 를 초과할 수 + 없습니다. 이 매개 변수는 애플리케이션의 합의 매개 변수에 정의되어 있습니다. +- 애플리케이션의 [`beginBlocker()`](../basics/app-anatomy.md#beginblocker-and-endblock) 를 수행합니다. 이는 주로 각 애플리케이션의 모듈의 + [`BeginBlocker()`](../building-modules/beginblock-endblock.md#beginblock) 메서드를 수행합니다. +- 애플리케이션의 [`VoteInfos`](https://tendermint.com/docs/app-dev/abci-spec.html#voteinfo) 를 설정합니다. 즉, 현재 블록의 제안자가 + 이전 블록에 포함된 _precommit_ 검증자 의 목록을 설정합니다. 이 정보는 [`Context`](./context.md) 에 전달되어 `DeliverTx` 와 + `EndBlock` 중에 사용할 수 있게 됩니다. + +### EndBlock + +[`EndBlock` ABCI 메시지](#https://tendermint.com/docs/app-dev/abci-spec.html#endblock) 는 블록의 각 트랜잭션에 대해 +[`DeliverTx`](#delivertx) 이 수행되고 난 후 Tendermint 엔진으로부터 보내집니다. 이로 인해 개발자들은 각 블록의 끝 부분에서 로직을 실행할 수 있습니다. +Cosmos SDK 에서 벌크 `EndBlock(req abci.RequestEndBlock)` 매서드는 애플리케이션의 +[`EndBlocker()`](../basics/app-anatomy.md#beginblocker-and-endblock) 를 실행합니다. 이는 주로 각 애플리케이션 모듈의 +[`EndBlocker()`](../building-modules/beginblock-endblock.md#beginblock) 메서드를 실행합니다. + +### Commit + +[`Commit` ABCI 메시지](https://tendermint.com/docs/app-dev/abci-spec.html#commit) 는 풀노드가 검증자의 2/3 이상 (voting +power 로 가중치가 적용된) 으로부터 _precommits_ 를 수신한 후 Tendermint 엔진으로부터 보내집니다. `BaseApp` 끝에서, +`Commit(res abci.ResponseCommit)` 함수 가 구현되어 `BeginBlock`, `DeliverTx` 와 `EndBlock` 동안 발생했던 모든 유효한 상태 전이가 커밋되며 +다음 블록을 위해 상태가 리셋됩니다. + +상태 전이를 커밋하기 위해, `Commit` 함수는 메인 저장소 `app.cms` 의 분기 멀티 저장소에 있는 `deliverState.ms` 의 `Write()` 함수를 호출합니다. +그런다음 `Commit` 함수는 `checkState` 를 최신 헤더 (`deliverState.ctx.BlockHeader` 에서 가져온) 에 설정하고, `deliverState` 를 `nil` 로 +설정합니다. + +마지막으로, `Commit` 은 `app.cms` 의 커밋 해시를 합의 엔진으로 다시 반환합니다. 이 해시는 다음 블록의 헤더 참조로 사용됩니다. + +### Info + +[`Info` ABCI 메시지](https://tendermint.com/docs/app-dev/abci-spec.html#info) 는 합의 엔진에서 나오는 간단한 쿼리이며, 특히 시작 시 +일어나는 핸드셰이크 중에 애플리케이션을 동기화하는데 사용됩니다. 호출되면 `BaseApp` 의 `Info(res abci.ResponseInfo)` 함수가 애플리케이션의 이름, 버전 +그리고 `app.cms`의 마지막 커밋 해시를 반환합니다. + +### 쿼리 (Query) + +[`Query` ABCI 메시지](https://tendermint.com/docs/app-dev/abci-spec.html#query) 는 Tendermint RPC 같은 RPC 를 통해 수신된 쿼리를 +포함하여 합의 엔진으로부터 수신된 쿼리를 제공합니다. 애플리케이션과의 인터페이스를 구축하기 위한 주요 진입점이었지만, Cosmos SDK v0.40 의 +[gRPC 쿼리](../building-modules/query-services.md) 소개에서는 그 사용이 제한적이 되었습니다. 애플리케이션은 `Query` 메서드 구현할 때 몇 가지 +규칙을 준수해야하며, [여기](https://tendermint.com/docs/app-dev/abci-spec.html#query) 에 설명되어 있습니다. + +각 Tendermint `query` 에는 쿼리할 대상을 나타내는 `string` 인 `path` 가 있습니다. 만약 `path` 가 gRPC 정규화 서비스 메서드와 일치하면, +`BaseApp` 은 쿼리를 `grpcQueryRouter` 로 연기하고 [위에서](#grpc-query-router) 설명한 대로 처리할 수 있도록 합니다. 그렇지 않으면, `path` 는 +gRPC 라우터에 의해 (아직) 처리되지 않는 쿼리입니다. `BaseApp` 은 `path` 문자열을 `/` 구분자로 나눕니다. +컨벤션에 따르면, 첫 번째 분할 문자열(`splitted[0]`) 은 `query` 의 카테고리 (`app`, `p2p`, `store` 또는 `custom`) 을 포함하고 있습니다. +`Query(req abci.RequestQuery)` 메서드의 `BaseApp` 구현은 간단한 디스패쳐이고, 다음과 같은 4 가지 주요 쿼리 카테고리를 지원합니다: + +- 애플리케이션 버전 같은 애플리케이션 관련 쿼리는 `handlerQueryApp` 메서드를 통해 지원합니다. +- 멀티 저장소로의 직접 쿼리는 `handlerQueryStore` 메서드를 통해 지원합니다. 이 직접 쿼리들은 `app.queryRouter` 를 통하는 커스텀 쿼리와는 다르며, + 주로 블록 탐색기와 같은 서드파티 서비스 제공자들이 사용합니다. +- P2P 쿼리는 `handlerQueryP2P` 메서드를 통해 지원합니다. 이 쿼리들은 주소를 `app.addrPeerFilter` 혹은 `app.ipPeerFilter` 를 반환하는데, + 이들은 각각 주소와 IP로 필터링한 피어 리스트를 포함하고 있습니다. 이 리스트들은 `BaseApp` 의 [생성자](#생성자-(constructor)) 에서 `options` 를 통해 + 초기화됩니다. + +## Next {hide} + +[트랜잭션](./transactions.md) 에 대해서 알아보세요. {hide} diff --git a/docs/ko/core/baseapp_state-begin_block.png b/docs/ko/core/baseapp_state-begin_block.png new file mode 100644 index 000000000..745d4a5a9 Binary files /dev/null and b/docs/ko/core/baseapp_state-begin_block.png differ diff --git a/docs/ko/core/baseapp_state-checktx.png b/docs/ko/core/baseapp_state-checktx.png new file mode 100644 index 000000000..38b217acd Binary files /dev/null and b/docs/ko/core/baseapp_state-checktx.png differ diff --git a/docs/ko/core/baseapp_state-commit.png b/docs/ko/core/baseapp_state-commit.png new file mode 100644 index 000000000..b23c73125 Binary files /dev/null and b/docs/ko/core/baseapp_state-commit.png differ diff --git a/docs/ko/core/baseapp_state-deliver_tx.png b/docs/ko/core/baseapp_state-deliver_tx.png new file mode 100644 index 000000000..f0a54b4ec Binary files /dev/null and b/docs/ko/core/baseapp_state-deliver_tx.png differ diff --git a/docs/ko/core/baseapp_state-initchain.png b/docs/ko/core/baseapp_state-initchain.png new file mode 100644 index 000000000..d03e88ef2 Binary files /dev/null and b/docs/ko/core/baseapp_state-initchain.png differ diff --git a/docs/ko/core/baseapp_state_types.png b/docs/ko/core/baseapp_state_types.png new file mode 100644 index 000000000..a7f91a609 Binary files /dev/null and b/docs/ko/core/baseapp_state_types.png differ diff --git a/docs/ko/core/node.md b/docs/ko/core/node.md new file mode 100644 index 000000000..fbb0e281d --- /dev/null +++ b/docs/ko/core/node.md @@ -0,0 +1,90 @@ + + +# 노드 클라이언트 (Daemon) + +SDK 애플리케이션의 주요 엔드포인트는 damon 클라이언트, 아니면 풀노드 클라이언트입니다. 풀노드는 상태 기계를 수행하고, 제네시스 파일로부터 시작합니다. 이 +클라이언트는 트랜잭션을 받고, 전달하고, 블록을 제안하고 서명하기 위해 똑같은 클라이언트를 실행하는 피어들과 연결되어 있습니다. 풀노드는 Cosmos SDK 로 정의된 +애플리케이션과 ABCI 를 통해 애플리케이션에 연결된 합의 엔진으로 구성됩니다. {synopsis} + +## 사전 요구 학습 + +- [SDK 애플리케이션 해부](../basics/app-anatomy.md) {prereq} + +## `main` 함수 + +모든 SDK 애플리케이션의 풀노드 클라이언트는 `main` 함수 수행으로 빌드됩니다. 클라이언트는 일반적으로 애플리케이션 이름 뒤에 `-d` 를 추가하고 (예 `appd` +의 애플리케이션 이름은 `app`), `main` 함수는 `./appd/cmd/main.go` 파일에 정의됩니다. 이 함수를 수행해 명령어 셋과 함께 제공되는 실행가능한 `appd` 가 +생성됩니다. `app` 이름을 가진 앱의 풀노드를 실행하는 주 명령어는 [`appd start`](#start-command) 가 됩니다. + +일반적으로, 개발자는 다음의 구조로 `main.go` 함수를 구현할 것입니다: + +- 먼저, 애플리케이션을 위한 [`appCodec`](./encoding.md) 을 인스턴스화 합니다. +- 그리고 `config` 를 검색하고 설정 매개 변수가 설정됩니다. 이는 주로 [주소](../basics/accounts.md#addresses) 에 대한 Bech32 프리픽스 설정이 + 포함됩니다. + +++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/types/config.go#L13-L24 + +- [Cobra](https://github.com/spf13/cobra) 를 사용해 풀노드 클라이언트의 루트 명령어가 생성됩니다. 그런 다음 애플리케이션의 모든 커스텀 명령어는 + `roomCmd` 의 `AddCommnad()` 를 사용해 추가됩니다. +- `server.AddCommnads()` 를 사용해 `roomCmd` 에 기본 서버 명령어들을 추가합니다. 이 명령어들은 표준이며 SDK 수준에서 정의되므로 위에서 추가한 + 명령어들과는 구분됩니다. 이 명령어들은 모든 SDK 기반 애플리케이션에서 공유되어야 합니다. 가장 중요한 [`start` 명령어](#start-command) 도 여기 포함되어 + 있습니다. +- `executor` 의 준비 및 실행 + +++ https://github.com/tendermint/tendermint/blob/v0.34.0-rc6/libs/cli/setup.go#L74-L78 + +데모용 SDK 애플리케이션인 `simapp` 의 `main` 함수 예제를 참조하세요: ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/simapp/simd/main.go + +## `start` 명령어 + +`start` 명령어는 Cosmos SDK 의 `/server` 폴더에 정의되어 있습니다. [`main` 함수](#main-function) 에서 풀노드 클라이언트의 루트 명령어로 +추가되어있으며, 엔드유저가 자신의 노드를 시작하기 위해 호출합니다. + +```bash +# "app" 이름의 앱 예시. 다음 명령어로 풀노드를 시작합니다. +appd start + +# SDK 의 simapp. 다음 명령어로 simapp 노드를 시작합니다. +simd start +``` + +참고로 풀노드는 세 가지 개념적 레이어로 구성됩니다: 네트워킹 레이어, 합의 레이어 그리고 애플리케이션 레이어. 첫 번째와 두 번째는 합의 엔진 (기본은 +Tendermint 코어) 이라고 불리는 엔티티에 함께 묶여있습니다. 세 번째 Cosmos SDK 의 도움을 받아 정의된 상태 기계입니다. 현재 Cosmos SDK 는 +Tendermint 를 기본 합의 엔진으로 사용하는데, Tendermint 노드를 부팅하기 위한 시작 명령어가 구현되어 있습니다. + +`start` 명령어의 흐름은 매우 간단합니다. 먼저 `db` (디폴트는 [`leveldb`](https://github.com/syndtr/goleveldb) 인스턴스) 를 열기 위해 +`context` 에서 `config` 를 검색합니다. 이 `db` 는 애플리케이션에 대해 알고있는 최신 상태를 포함하고 있습니다. (이 애플리케이션이 처음이라면 비어있음) + +`start` 명령어는 `db` 와 `appCreator` 함수를 사용해 애플리케이션의 새 인스턴스를 생성합니다. ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/server/start.go#L227-L228 + +`appCreator` 는 `AppCreator` 시그니처를 만족하는 함수입니다: ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/server/types/app.go#L48-L50 + +실제로, [애플리케이션의 생성자](../basics/app-anatomy.md#constructor-function) 는 `appCreator` 로 전달됩니다. ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/simapp/simd/cmd/root.go#L170-L215 + +그리고나서 `app` 의 인스턴스를 사용해 새로운 Tendermint 노드를 인스턴스화 합니다. ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/server/start.go#L235-L244 + +`app` 이 [`abci.Application` 인터페이스](https://github.com/tendermint/tendermint/blob/v0.34.0/abci/types/application.go#L7-L32) +(`app` 이 [`baseapp`](./baseapp.md) 의 확장인 경우) 를 만족하기 때문에 Tendermint 노드는 `app` 으로 생성될 수 있습니다. `NewNode` 메소드의 +일부분으로, Tendermint 는 애플리케이션의 높이 (즉, 제네시스 블록으로부터의 블록넘버) 가 Tendermint 노드의 높이와 동일한지 확인합니다. 두 높이의 차이는 +항상 음수나 null 이 되어야 합니다. 음수라면, `NewNode` 는 애플리케이션의 높이가 Tendermint 노드의 높이에 도달할 때까지 블록을 리플레이할 것입니다. +마지막으로, 만약 애플리케이션의 높이가 `0` 이라면 Tendermint 노드는 제네시스 파일을 사용해 상태를 초기화하기 위해 애플리케이션에서 +[`InitChain`](./baseapp.md#initchain) 을 호출할 것입니다. + +Tendermint 노드가 인스턴스화되고 애플리케이션과 동기화되면, 노드는 시작할 수 있습니다: ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/server/start.go#L250-L252 + +노드가 시작되면, 노드는 P2P 서버와 RPC 를 부트스트랩하고 피어에 연결을 시작합니다. 피어들과 핸드셰이크 중, 만약 다른 피어들이 앞서 있다는 것 알아채면, 노드는 +따라잡기 위해 모든 블록들을 순차적으로 쿼리할 것입니다. 그러고나서 새로운 블록 제안과 Validator 로부터 블록 처리를 위한 블록 서명을 기다립니다. + +## 다른 명령어들 + +노드를 구체적으로 실행하고, 노드와 상호작용하는 방법은 [노드 수행, API 와 CLI](../run-node/README.md) 가이드를 참조하세요. + +## Next {hide} + +[store](./store.md) 에 대해서 알아보세요. {hide} \ No newline at end of file diff --git a/docs/ko/core/ocap.md b/docs/ko/core/ocap.md new file mode 100644 index 000000000..faf49b296 --- /dev/null +++ b/docs/ko/core/ocap.md @@ -0,0 +1,63 @@ + + +# 오브젝트 자격 모델 (Object-Capability Model) + +## 소개 + +보안을 고려할 때는 구체적인 위협 모델로부터 시작하는게 좋습니다. 우리의 위협 모델은 다음과 같습니다: + +> 블록체인 애플리케이션을 쉽게 구성할 수 있는 활발한 Cosmos SDK 모듈 생태계는 결함있거나 악의적인 모듈이 포함될 수 있습니다. + +Cosmos SDK 는 오브젝트 자격 모델의 기반이 되어 이런 위협에 대처하도록 설계되었습니다. + +> 오브젝트 자격 시스템의 구조적 특성은 코드 설계에서는 모듈화를 선호하게 하고, 코드 구현에서는 신뢰할 수 있는 인캡슐레이션(encapsulation) 을 보장합니다. +> +> 이러한 구조적 특성은 오브젝트 자격 프로그램 또는 시스템 운영의 일부 보안 특성을 분석하는데 도움이 됩니다. 이 중 일부 (특히, 정보 흐름 특성) 는 오브젝트 +> 동작을 결정하는 코드에 대한 지식이나 분석이 필요없이 오브젝트 참조 및 연결 수준에서 분석이 가능합니다. +> +> 따라서 이러한 보안 특성은 알려져있지 않고 악성일 수도 있는 코드가 포함된 새로운 오브젝트가 있는 경우에도 확립되고 유지보수할 수 있습니다. +> +> 이 구조적 특성들은 기존 오브젝트에 대한 접근을 제어하는 두 가지 규칙에서 비롯됩니다: +> +> 1. 오브젝트 A 는 B 에 대한 참조를 가지고 있을 때에만 B 로 메시지를 보낼 수 있습니다. +> +> 2. 오브젝트 A 는 C 에 대한 참조를 포함하는 메시지를 수신한 경우에만 C 에 대한 참조를 얻을 수 있습니다. 이 두 가지 규칙에 따라서, 오브젝트는 기존 참조 + 체인을 통해서만 다른 오브젝트의 참조를 얻을 수 있습니다. 간단히 말해서, "오직 연결만이 연결을 낳는다" + +오브젝트 자격에 대한 소개는 [Wikipedia article](https://en.wikipedia.org/wiki/Object-capability_model) 을 참조하세요. + +## 실전 Ocaps + +작업에 필요한 것들만 알아봅시다. + +예를 들어, 다음 코드 스니펫은 오브젝트 자격 원칙을 위반했습니다: + +```go +type AppAccount struct {...} +account := &AppAccount{ + Address: pub.Address(), + Coins: sdk.Coins{sdk.NewInt64Coin("ATM", 100)}, +} +sumValue := externalModule.ComputeSumValue(account) +``` + +`ComputSumValue` 는 순수 함수이지만, 포인터를 받으면 그 값을 수정할 수도 있음을 의미합니다. +이것 대신에 선호되는 메서드 시그니처 방식은 값을 복사하는 것입니다. + +```go +sumValue := externalModule.ComputeSumValue(*account) +``` + +Cosmos SDK 에서는 gaia 앱에서 이 원칙을 적용한 것을 볼 수 있습니다. + ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.41.4/simapp/app.go#L249-L273 + +다음의 다이어그램은 현재 keeper 들 간의 의존관계를 보여 줍니다. + +![Keeper 의존관계](../../uml/svg/keeper_dependencies.svg) + +## Next {hide} + +[`runTx` 미들웨어](./runtx_middleware.md) 에 대해서 알아보세요 {hide} diff --git a/docs/ko/core/transactions.md b/docs/ko/core/transactions.md new file mode 100644 index 000000000..9cc5af3d1 --- /dev/null +++ b/docs/ko/core/transactions.md @@ -0,0 +1,195 @@ + + +# 트랜잭션 (Transactions) + +`Transactions` 는 엔드유저에 의해 생성되는 객체로써 애플리케이션에서 상태 변경을 트리거합니다. {synopsis} + +## 사전 요구 학습 + +- [SDK Application 해부](../basics/app-anatomy.md) {prereq} + +## 트랜잭션 (Transactions) + +트랜잭션은 [contexts](./context.md) 의 메타데이터와 모듈의 Protobuf [`Msg` 서비스](../building-modules/msg-services.md) 를 통해 +모듈 내의 상태 변경을 트리거하는 [`sdk.Msg`](../building-modules/messages-and-queries.md) 로 구성됩니다. + +사용자가 애플리케이션과 상호작용하여 상태를 변경 (예: 코인 전송) 하고 싶을 때 트랜잭션을 생성합니다. 트랜잭션의 각 `sdk.Msg` 는 트랜잭션이 네트워크로 브로드캐스팅 +되기 전에, 반드시 해당 계정에 연결된 개인키를 사용하여 서명되어야 합니다. 그런 다음에 트랜잭션은 합의 프로세스를 통해 네트워크가 검증, 승인하고 블록에 포함됩니다. +트랜잭션 생명주기에 대해서 더 읽어보시려면 [여기](../basics/tx-lifecycle.md) 를 클릭하세요. + + +## 타입 정의 (Type Definition) + +트랜잭션 객체는 `Tx` 인터페이스를 구현한 SDK 타입입니다. + ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/types/tx_msg.go#L49-L57 + +다음의 메서드들을 포함합니다: + +- **GetMsgs:** 트랜잭션의 래핑을 풀고 `sdk.Msg` 목록을 반환합니다. - 하나의 트랜잭션은 하나 이상의 메시지를 포함할 수 있으며, 이는 모듈 개발자가 정합니다. +- **ValidateBasic:** 가벼운 [_stateless_](../basics/tx-lifecycle.md#types-of-checks) 검사가 포함되어 ABCI 메시지인 + [`CheckTx`](./baseapp.md#checktx) 와 [`DeliverTx`](./baseapp.md#delivertx) 에서 사용되며, 이를 통해 유효하지 않은 트랜잭션인지 + 확인합니다. 예를 들어, [`auth`](https://github.com/cosmos/cosmos-sdk/tree/master/x/auth) 모듈의 `StdTx` `ValidateBasic` 함수는 + 정확한 숫자의 서명자가 서명했는지 확인하고 수수료가 사용자의 최대 금액을 초과하지 않는지 확인합니다. 이 함수는 `sdk.Msg` 의 메시지에 대해 기본적인 유효성 + 검사만 수행하는 `ValidateBasic` 함수들과 구분해야한다는 점을 주의하십시오. 예를 들어, + [`auth`](https://github.com/cosmos/cosmos-sdk/tree/master/x/auth/spec) 모듈에서 만들어진 트랜잭션을 + [`runTx`](./baseapp.md#runtx) 에서 검사할 때, 각 메시지에 대해 `ValidateBasic` 를 먼저 실행하고 트랜잭션 자체에 대해 `ValidateBasic` 을 + 호출하는 `auth` 모듈 `AnteHandler` 를 실행합니다. + +`Tx` 는 실제로 트랜잭션 생성에 사용되는 중간 타입이기 때문에, 개발자는 `Tx` 를 직접 조작하는 일이 거의 없습니다. 대신에 개발자는 `TxBuilder` 인터페이스를 +더 선호할 것이고, [아래](#transaction-generation)에서 더 알아볼 수 있습니다. + +### 트랜잭션 서명 (Signing Transactions) + +트랜잭션의 모든 메시지는 해당되는 `GetSigners` 에서 지정한 주소로 서명되어야 합니다. SDK 는 현재 두 가지 방법으로 트랜잭션 서명을 허용합니다. + +#### `SIGN_MODE_DIRECT` (선호됨) + +가장 많이 사용되는 `Tx` 인터페이스 구현은 `SIGN_MODE_DIRECT` 에서 사용되는 Protobuf `Tx` 메시지입니다: + ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/proto/cosmos/tx/v1beta1/tx.proto#L12-L25 + +프로토콜 버퍼 직렬화는 결정론적이지 않기 때문에, SDK 는 추가적인 `TxRaw` 타입을 사용해서 트랜잭션이 서명되는 고정 바이트를 표시합니다. 모든 사용자는 트랜잭션에 +대한 유효한 `body` 와 `auth_info` 를 생성할 수 있으며, Protobuf 를 사용해 두 메시지를 직렬화할 수 있습니다. 그런 다음 `TxRaw` 는 각각 +`body_bytes`와 `auth_info_bytes` 라고 불리는 `body` 와 `auth_info` 의 사용자의 정확한 바이너리 표현(binary representation)을 고정합니다. +`SignDoc` ([ADR-027](../architecture/adr-027-deterministic-protobuf-serialization.md) 을 사용해서 결정론적으로 직렬화된) 은 +트랜잭션의 모든 서명자에 의해 서명된 문서입니다: + ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/proto/cosmos/tx/v1beta1/tx.proto#L47-L64 + +모든 서명자가 서명하면 `body_bytes`, `auth_info_bytes` 와 `signatures` 는 `TxRaw` 로 수집되고, 바이트 직렬화되어 네트워크로 브로드캐스트됩니다. + +#### `SIGN_MODE_LEGACY_AMINO_JSON` + +`x/auth` 의 `StdTx` 구조체 인 `Tx` 인터페이스의 기존 구현: + ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/x/auth/legacy/legacytx/stdtx.go#L120-L130 + +모든 서명자에 의해 서명된 문서인 `StdSignDoc`: + ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/x/auth/legacy/legacytx/stdsign.go#L20-L33 + +`StdSignDoc` 은 Amino JSON 을 사용하여 바이트로 인코드 됩니다. 모든 서명이 `StdTx` 로 수집되면, `StdTx` 는 Amino JSON 을 사용해 직렬화되고, +이 바이트들은 네트워크를 통해 브로드캐스트됩니다. + +#### Other Sign Modes + +기타 서명 모드로는 특히 `SIGN_MOD_TEXTUAL` 이 논의되고 있습니다. 이에 대해 더 알아보시려면 +[ADR-020](../architecture/adr-020-protobuf-transaction-encoding.md) 을 참조하세요. + +## 트랜잭션 프로세스 + +엔드유저가 트랜잭션을 보내는 프로세스는: + +- 트랜잭션으로 넣을 메시지 결정 +- SDK 의 `TxBuilder` 를 사용해서 트랜잭션 생성 +- 가능한 인터페이스 중 하나를 사용해 트랜잭션 브로드캐스트 + +다음 단락에서는 이러한 구성 요소들을 다음 순서로 설명합니다. + +### 메시지 (Messages) + +::: tip +모듈 `sdk.Msg` 를 애플리케이션 레이어와 Tendermint 간 상호작용을 정의하는 +[ABCI 메시지](https://tendermint.com/docs/spec/abci/abci.html#messages) 와 혼동하면 안됩니다. +::: + +**메시지** (또는 `sdk.Msg`) 는 해당 메시지가 속한 모듈의 범위 내에서 상태 전이를 트리거 하는 모듈별 전용 객체입니다. 모듈 개발자들은 +Protobuf [`Msg` 서비스](../building-modules/msg-services.md) 에 메서드를 추가해서 그들의 모듈을 위한 메시지를 정의하고, 또한 해당하는 +`MsgServer` 를 구현합니다. + +각 `sdk.Msg` 는 각 모듈의 `tx.proto` 파일 내에 정의된 정확한 하나의 Protobuf [`Msg` 서비스](../building-modules/msg-services.md) +RPC 와 관련되어 있습니다. SDK 앱 라우터는 해당 RPC 로 매 `sdk.Msg` 를 자동으로 매핑합니다. Protobuf 는 각 모듈 `Msg` 서비스를 위한 `MsgServer` +인터페이스를 생성하는데, 모듈 개발자는 이 인터페이스를 구현해야 합니다. 이 설계는 모듈 개발자에게 더 많은 책임을 부여하고, 애플리케이션 개발자가 상태 전이 +로직을 반복적으로 구현하지 않고 공통 기능을 재사용 하게끔 합니다. + +Protobuf `Msg` 와 `MsgServer` 구현에 대해서 더 알아보시려면, [여기](../building-modules/msg-services.md) 를 클릭하세요. + +상태 전이 로직에 대한 정보는 메시지에 포함되어 있고, 트랜잭션의 다른 메타 데이터 및 관련 정보는 `TxBuilder` 와 `Context` 에 저장됩니다. + +### 트랜잭션 생성 + +`TxBuilder` 인터페이스에는 트랜잭션 생성과 밀접하게 관련된 데이터가 포함되어 있습니다. 이 데이터는 엔드유저가 원하는 트랜잭션을 생성하도록 자유롭게 설정할 수 +있습니다. + ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/client/tx_config.go#L32-L45 + +- `Msg`, 트랜잭션에 포함된 [메시지](#messages) 배열 +- `GasLimit`, 지불해야 하는 가스를 계산하는 방법에 대해 사용자가 선택한 옵션 +- `Memo`, 트랜잭션과 함께 전송되는 메모 또는 코멘트 +- `FeeAmount`, 사용자가 수수료로 지불할 용의가 있는 최대양 +- `TimeoutHeight`, 트랜잭션이 유효할 때까지의 블록 높이 +- `Signatures`, 트랜잭션 모든 서명자의 서명 배열 + +트랜잭션 서명을 위해 현재 두 가지 서명 모드가 있으므로 `TxBuilder` 에도 두 가지 구현이 있습니다: + +- `SIGN_MODE_DIRECT` 용 트랜잭션 생성을 위한 [wrapper](https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/x/auth/tx/builder.go#L19-L33) +- `SIGN_MODE_LEGACY_AMINO_JSON` 용 [StdTxBuilder](https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/x/auth/legacy/legacytx/stdtx_builder.go#L14-L20) + +그러나 엔드유저는 `TxConfig` 인터페이스를 사용해야 하므로, `TxBuilder` 의 두 가지 구현은 엔드유저에게는 숨겨져 있습니다. + ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/client/tx_config.go#L21-L30 + +`TxConfig` 는 트랜잭션 관리를 위한 앱 전체 (app-wide) 설정입니다. 제일 중요한건, 각 트랜잭션의 서명에 `SIGN_MODE_DIRECT` 와 +`SIGN_MODE_LEGACY_AMINO_JSON` 중 어떤 것을 사용할 지에 대한 정보를 담고 있다는 것입니다. `txBuilder := txConfig.NewTxBuilder()` 를 +호출하여 설정된 서명 모드로 새로운 `TxBuilder` 가 생성됩니다. + +`TxBuilder` 가 위에서 말한 설정자들로 올바르게 채워지면, `TxConfig` 도 바이트를 올바르게 인코딩할 것입니다 (`SIGN_MODE_DIRECT` 또는 +`SIGN_MODE_LEGACY_AMINO_JSON` 를 사용해서). 다음은 `TxEncoder()` 메서드를 사용하여 어떻게 트랜잭션을 인코드하고 생성하는지에 대한 의사 코드 +스니펫입니다. + +```go +txBuilder := txConfig.NewTxBuilder() +txBuilder.SetMsgs(...) // and other setters on txBuilder + +bz, err := txConfig.TxEncoder()(txBuilder.GetTx()) +// bz are bytes to be broadcasted over the network +``` + +### 트랜잭션 브로드캐스팅 + +트랜잭션 바이트가 생성되면, 현재 세 가지 방법으로 그것을 브로드캐스팅합니다. + +#### CLI + +애플리케이션 개발자는 [커맨드라인 인터페이스](../core/cli.md), [gRPC 그리고(또는) REST 인터페이스](../core/grpc_rest.md) 를 생성하여 +애플리케이션으로의 진입점을 만듭니다. 이는 일반적으로 애플리케이션의 `./cmd` 폴더에서 찾을 수 있습니다. + +[커맨드라인 인터페이스](../building-modules/module-interfaces.md#cli) 의 경우, 모듈 개발자는 하위 명령어들을 생성하여 애플리케이션 최상위 트랜잭션 +커맨드 `TxCmd` 에 자식으로 추가합니다. CLI 커맨드는 실제로 하나의 커맨드에 트랜잭션 처리의 모든 단계가 묶여있습니다: 메시지 생성, 트랜잭션 생성 및 브로드캐스팅. +좋은 예로 [노드와 상호작용](../run-node/interact-node.md) 섹션을 보십시오. CLI 를 사용하여 만든 예시 트랜잭션: + +```bash +simd tx send $MY_VALIDATOR_ADDRESS $RECIPIENT 1000stake +``` + +#### gRPC + +[gRPC](https://grpc.io) 는 SDK 의 RPC 레이어를 위한 주요 구성 요소로써 Cosmos SDK 0.40 에서 도입되었습니다. gRPC 의 주요 용도는 모듈의 +[`Query` 서비스](../building-modules) 컨텍스트 입니다. 그러나 SDK 는 모든 모듈에 쓰일 수 있는 gRPC 서비스 몇 가지도 제공합니다. 그 중 하나는 `Tx` +서비스입니다. + ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/proto/cosmos/tx/v1beta1/service.proto + +`Tx` 서비스는 트랜잭션을 시뮬레이션하거나 트랜잭션을 쿼리하는 것과 같은 몇 가지 유틸리티 함수와 트랜잭션을 브로드캐스티하는 한가지 메서드를 제공합니다. + +트랜잭션 시뮬레이션과 브로드캐스팅에 대한 예제를 [여기](../run-node/txs.md#programmatically-with-go) 에서 볼 수 있습니다. + +#### REST + +각 gRPC 메서드는 [gRPC-gateway](https://github.com/grpc-ecosystem/grpc-gateway) 를 사용해서 생성되는 해당 REST 엔드포인트가 있습니다. +따라서 gRPC 를 사용하는 대신에, HTTP 를 사용해서 `POST /cosmos/tx/v1beta1/txs` 엔드포인트에서 같은 트랜잭션을 브로드캐스트할 수도 있습니다. + +[여기](../run-node/txs.md#using-rest) 에서 예제를 볼 수 있습니다. + +#### Tendermint RPC + +위에 나와있는 세 가지 메서드는 실제로 Tendermint RPC `/broadcast_tx_{async,sync,commit}` 엔드포인트 에 대한 높은 수준의 추상화 (higher +abstraction) 입니다. [여기](https://docs.tendermint.com/master/rpc/#/Tx) 문서를 참조하세요. 원한다면 Tendermint RPC 엔드포인트를 +사용하여 트랜잭션을 직접 브로드캐스트할 수 있다는 뜻입니다. + +## Next {hide} + +[context](./context.md) 에 대해서 알아보세요 {hide} diff --git a/docs/ko/intro/README.md b/docs/ko/intro/README.md new file mode 100644 index 000000000..d7953ff5d --- /dev/null +++ b/docs/ko/intro/README.md @@ -0,0 +1,16 @@ + + +# Introduction + +이 폴더는 Cosmos SDK에 대한 소개 자료를 담고 있습니다. + +1. [개요](overview.md) +2. [애플리케이션별 전용(Application-specific) 블록체인](./why-app-specific.md) +3. [SDK 애플리케이션 아키텍쳐](sdk-app-architecture.md) +4. [Cosmos SDK 디자인 개요](./sdk-design.md) + +소개 자료를 읽고 난 뒤, 더 알아보시려면 [basics](../basics/README.md)를 참고하세요. diff --git a/docs/ko/intro/overview.md b/docs/ko/intro/overview.md new file mode 100644 index 000000000..9a77f230c --- /dev/null +++ b/docs/ko/intro/overview.md @@ -0,0 +1,54 @@ + + +# High-level Overview + +## SDK 가 무엇인가요? + +[Cosmos SDK](https://github.com/cosmos/cosmos-sdk) 는 Cosmos Hub와 같이 다중자산(Multi-asset) 지분증명(Proof-of-Stake, PoS) 공개 +블록체인이나, 허가된 권한증명(Proof-of-Authority, PoA) 블록체인을 만들기 위한 오픈소스 프레임워크입니다. + +Cosmos SDK 의 목적은 다른 블록체인과의 상호작용이 기본적으로 가능한 커스텀 블록체인을 개발자들이 쉽게 직접 만들 수 있도록 하는 것입니다. 우리는 +Cosmos SDK 가 [Tendermint](https://github.com/tendermint/tendermint) 기반에서 안정적인 블록체인 애플리케이션을 구축하기 위한 프레임워크, +npm 같은 프레임워크가 되기를 기대합니다. Cosmos SDK 기반의 블록체인들은 컴포저블 [모듈](../building-modules/intro.md)(Composable modules)로 +만들어지며, 이들 대부분은 오픈소스이고 모든 개발자들이 쉽게 사용할 수 있습니다. 누구나 Cosmos SDK 용 모듈을 만들 수 있고, 만들어진 모듈들을 통합하는건 +당신의 블록체인 애플리케이션으로 import만 하면 됩니다. 뿐만아니라 Cosmos SDK 는 자격 기반 시스템(Capabilities-based system) 으로써 개발자들이 +모듈간 상호작용의 보안성에 대해 더 나은 판단을 할 수 있게 합니다. 자격에 대한 더 심도있는 내용을 보려면 [이 섹션](../core/ocap.md) 을 참고하세요. + +## 애플리케이션별 전용 블록체인(Application-Specific Blockchains) 이란? + +오늘날 블록체인 세계에서의 한 가지 개발 패러다임은 Ethereum 과 같은 가상 머신 블록체인으로써, 일반적으로는 기존 블록체인 위에 분산형 애플리케이션을 스마트 +컨트랙트로 구축하는 것이 핵심입니다. 스마트 컨트랙트는 일회용 애플리케이션(e.g. ICOs) 같은 어떤 유스케이스에는 매우 좋을 수 있지만, 복잡한 분산형 플랫폼을 +만들 때에는 부족한 경우가 많습니다. 일반적으로 스마트 컨트랙트는 유연성, 자주성과 성능 측면에서 제한적일 수 있습니다. + +애플리케이션별 전용 블록체인은 가상 머신 블록체인과는 근본적으로 다른 개발 패러다임을 제공합니다. 애플리케이션별 전용 블록체인은 하나의 애플리케이션 운용을 위해 +맞춤화된 블록체인입니다: 개발자는 애플리케이션을 최적으로 실행하는데에 필요한 설계 결정을 자유롭게 내릴 수 있습니다. 또한 더 나은 자주성, 보안, 성능을 제공할 수 +있습니다. + +[애플리케이션별 전용 블록체인](./why-app-specific.md) 에 대해 자세히 알아보기. + +## 왜 Cosmos SDK인가? + +Cosmos SDK 는 맞춤형 애플리케이션별 전용 블록체인 구축을 위한 오늘날 가장 진보한 프레임워크입니다. 다음은 왜 Cosmos SDK 로 분산형 어플리케이션을 +만들어야하는지에 대한 몇가지 이유입니다: + +- SDK 에서 사용할 수 있는 기본 합의 엔진은 [Tendermint Core](https://github.com/tendermint/tendermint) 입니다. Tendermint 는 현존하는 + BFT 합의 엔진 중 가장(그리고 유일하게) 성숙한 엔진입니다. 업계 전반에서 널리 사용되며 지분증명 시스템 구축에 최적 표준의 합의 엔진으로 여겨집니다. +- SDK 는 오픈소스이며 컴포저블 [모듈](../../x/) 로 쉽게 블록체인을 구축할 수 있도록 설계되었습니다. 오픈소스 모듈 생태계가 성장함에 따라, 이를 통해 복잡한 + 분산형 플랫폼을 구축하는것이 점점 더 쉬워질 것입니다. +- SDK 는 자격기반 보안에서 영감을 받았으며, 수년간 블록체인 상태 기계와 씨름하며 얻은 정보입니다. 따라서 Cosmos SDK 는 블록체인을 구축하기에 매우 + 안정적인 환경입니다. +- 가장 중요한 것은, Cosmos SDK 는 이미 개발 중인 많은 애플리케이션별 전용 블록체인들을 구축하는데에 사용되고 있습니다. + [Cosmos Hub](https://hub.cosmos.network), [IRIS Hub](https://irisnet.org), [Binance Chain](https://docs.binance.org/), + [Terra](https://terra.money/) or [Kava](https://www.kava.io/) 등을 예로 들 수 있습니다. 이외에도 + [더 많은 곳](https://cosmos.network/ecosystem) 에서 Cosmos SDK 를 기반으로 구축되고 있습니다. + +## Cosmos SDK 시작하기 + +- [SDK 애플리케이션 아키텍쳐](sdk-app-architecture.md) 자세히 알아보기 +- [SDK 튜토리얼](https://cosmos.network/docs/tutorial) 을 통해 직접 애플리케이션별 전용 블록체인 구축하는 법 알아보기 + +## Next {hide} + +[애플리케이션별 전용 블록체인](./why-app-specific.md) 알아보기 {hide} diff --git a/docs/ko/intro/sdk-app-architecture.md b/docs/ko/intro/sdk-app-architecture.md new file mode 100644 index 000000000..963c738c8 --- /dev/null +++ b/docs/ko/intro/sdk-app-architecture.md @@ -0,0 +1,119 @@ + + +# 블록체인 아키텍쳐 + +## 상태 기계 (State machine) + +블록체인은 근본적으로 [복제된 결정론적 상태 기계(replicated deterministic state machine)](https://en.wikipedia.org/wiki/State_machine_replication) 입니다. + +상태 기계는 기계가 다양한 상태를 가질 수 있으나, 한 시점에는 오직 하나의 상태만을 가져야하는 컴퓨터 공학 개념입니다. `state` 는 시스템의 현재 상태를 나타내고, +`transactions` 는 상태 변화를 트리거합니다. + +상태 S 와 트랜잭션 T 가 주어지면, 상태 기계는 새로운 상태 S' 를 반환할 것입니다. + +``` ++--------+ +--------+ +| | | | +| S +---------------->+ S' | +| | apply(T) | | ++--------+ +--------+ +``` + +실제로는 보다 효율적인 프로세스를 위해서 트랜잭션들은 블록으로 묶음처리 됩니다. 상태 S와 트랜잭션 블록B 가 주어지면, 상태 기계는 새로운 상태 S' 를 반환할 것입니다. + +``` ++--------+ +--------+ +| | | | +| S +----------------------------> | S' | +| | For each T in B: apply(T) | | ++--------+ +--------+ +``` + +블록체인 개념 내에서, 상태 기계는 결정론적입니다. 이 뜻은 노드가 어떤 상태에서 트랜잭션 시퀀스를 수행하는 것을 동일하게 여러번 반복해도, 항상 같은 최종 상태에 +도달한다는 것입니다. + +Cosmos SDK 는 개발자들에게 애플리케이션 상태와 트랜잭션 타입, 상태 변화 기능을 정의하는 것에 최대한의 유연성을 제공합니다. Cosmos SDK 와 상태 기계를 +구축하는 프로세스는 이어지는 섹션에서 보다 자세하게 설명하겠습니다. 우선, **Tendermint** 를 사용해서 어떻게 상태 기계를 복제하는지 알아보겠습니다. + +## Tendermint + +Cosmos SDK 덕분에, 개발자들은 단지 상태 기계만 정의하면 됩니다. +[*Tendermint*](https://tendermint.com/docs/introduction/what-is-tendermint.html) 가 네트워크를 통해 그들을 복제하는 것을 처리할 것입니다. + +``` + ^ +-------------------------------+ ^ + | | | | Cosmos SDK로 빌드 + | | 상태 기계 = 애플리케이션ㅤㅤㅤㅤ| | + | | | v + | +-------------------------------+ + | | | ^ + 블록체인 노드 ㅤ| | 합의(consensus)ㅤㅤㅤㅤㅤ | | + | | | | + | +-------------------------------+ | Tendermint 코어 + | | | | + | | 네트워크 ㅤㅤㅤ| | + | | | | + v +-------------------------------+ v +``` + +[Tendermint](https://tendermint.com/docs/introduction/what-is-tendermint.html) 는 애플리케이션-애그노스틱(Application-agnostic) +엔진으로써 블록체인의 *네트워크* 및 *합의* 레이어를 처리하는것을 책임집니다. 즉, Tendermint 는 트랜잭션 바이트의 전송 및 바이트 순서 정렬(ordering)을 +담당한다는 뜻입니다. Tendermint 코어는 비잔틴 장애 허용(Byzantine-Fault-Tolerant, BFT) 알고리즘을 사용하여 트랜잭션 순서 합의에 도달합니다. + +Tendermint [합의 알고리즘](https://docs.tendermint.com/v0.34/introduction/what-is-tendermint.html#consensus-overview) 은 +*검증자 (Validator)* 라는 특수한 노드들의 세트와 함께 작동합니다. 검증자 는 트랜잭션 블록들을 블록체인에 추가하는 역할을 합니다. 어떤 블록이라도 검증자 +세트 V 가 있습니다. V 의 검증자 중 하나가 알고리즘에 의해 다음 제안자(proposer) 로 선택됩니다. V 의 검증자 3분의 2 이상이 +*[prevote](https://docs.tendermint.com/v0.34/spec/consensus/consensus.html#prevote-step-height-h-round-r)* 와 +*[precommit](https://docs.tendermint.com/v0.34/spec/consensus/consensus.html#precommit-step-height-h-round-r)* 에 서명하고, +포함된 모든 트랜잭션이 유효한 경우 이 블록도 유효한 것으로 간주됩니다. 검증자 세트는 상태 기계 내에 작성된 규칙에 따라서 바뀔 수 있습니다. + +## ABCI + +Tendermint 는 [ABCI](https://docs.tendermint.com/v0.34/spec/abci/) 라는 인터페이스를 통해 애플리케이션으로 트랜잭션을 전달합니다. +이 ABCI 는 애플리케이션이 반드시 구현해야 하는 부분입니다. + +``` + +---------------------+ + | | + | Application | + | | + +--------+---+--------+ + ^ | + | | ABCI + | v + +--------+---+--------+ + | | + | | + | Tendermint | + | | + | | + +---------------------+ +``` + +**Tendermint 는 오직 트랜잭션 바이트들만 처리합니다**. 그 바이트들의 의미까지는 알지 못합니다. Tendermint 가 하는 일은 이 트랜잭션 바이트들을 결정론적으로 +정렬하는 것 뿐입니다. Tendermint 는 ABCI 를 통해 애플리케이션으로 바이트를 전달하고, 트랜잭션에 포함된 메시지 처리의 성공 여부를 반환된 코드가 알려주기를 +기대합니다. + +아래는 ABCI 에서 가장 중요한 메시지들입니다. + +- `CheckTx`: Tendermint 코어에서 트랜잭션을 수신하면, 애플리케이션으로 전달되어 몇가지 기본적인 요구사항이 충족되는지 확인합니다. `CheckTx` 는 스팸 + 트랜잭션들로부터 전체 노드들의 메모리 풀을 보호하는데 사용됩니다. `AnteHandler` 라는 특별한 핸들러는 수수료는 충분한지, 서명이 유효한지 등과 같은 일련의 + 검증 단계를 수행합니다. 모든 검사가 통과되면, 트랜잭션은 메모리 풀에 추가되고 피어 노드들에게 전달됩니다. 트랜잭션이 아직 블록에 담기지 않았기 때문에 + `CheckTx` 로 트랜잭션이 처리된것은 아닙니다.(즉, 상태 변경이 일어난것이 아님) +- `DeliverTx`: Tendermint 코어에서 [유효한 블록](https://docs.tendermint.com/v0.34/spec/blockchain/blockchain.html#validation) 을 + 수신하면, 블록의 각 트랜잭션은 처리를 위해 `DeliverTx` 를 통해서 애플리케이션으로 전달됩니다. 이 단계에서 상태 변경이 발생합니다. `AnteHandler` 는 + 트랜잭션의 각 메시지를 위한 실제 [`Msg` service](../building-modules/msg-services.md) RPC 와 함께 다시 실행됩니다. +- `BeginBlock`/`EndBlock`: 이 메시지들은 블록내 트랜잭션 포함여부와 관계없이 각 블록의 시작과 끝에서 실행됩니다. 이는 로직의 자동실행을 트리거하기에 + 유용합니다. 하지만 컴퓨팅 비용이 비싼 루프로 인해 블록체인이 느려질 수도 있고, 무한 루프라면 심지어 멈출 수도 있으므로 주의해야 합니다. + +ABCI 메서드에 대해 더 자세한 내용은 [Tendermint docs](https://docs.tendermint.com/v0.34/spec/abci/abci.html#overview) 에서 찾을 수 +있습니다. + +Tendermint 를 기반으로 하는 모든 애플리케이션은 레이어 하부의 로컬 Tendermint 엔진과 상호작용을 하기위해 ABCI 인터페이스를 구현해야 하지만, 다행히 이를 +직접하지 않아도 됩니다. Cosmos SDK 가 [baseapp](./sdk-design.md#baseapp) 형태로 보일러플레이트 구현을 제공합니다. + +## Next {hide} + +[SDK 의 하이레벨 설계 원칙](./sdk-design.md) 에 대해서 읽어보세요 {hide}