본문 바로가기

Hyperledger Fabric/Document

[HYPERLEDGER FABRIC v1.1]Operations Guides

Upgrading from v1.0.x

Upgrading from v1.0.x(v1.0.x에서 업그레이드)

1.0.x 버전에서 패브릭 네트워크를 v1.1로 업그레이드하는 작업은 다음 단계를 수행하여 완료할 수 있습니다.

  • orderers, peers 및 fabric-ca용 바이너리를 업그레이드하십시오. 이러한 업그레이드는 병행하여 수행할 수 있습니다.
  • 클라이언트 SDK를 업그레이드하십시오.
  • v1.1 채널 기능 요구 사항을 사용합니다.
  • (선택 사항) Kafka 클러스터를 업그레이드합니다.

이 과정을 이해하는데 도움이 되도록 Upgrading Your Network Components(네트워크 구성요소 업그레이드) 튜토리얼을 만들었습니다. 이 튜토리얼을 통해 peers, orderers 업그레이드 및 기능 요구 사항 활성화를 비롯한 대부분의 주요 업그레이드 단계를 수행 할 수 있습니다.

이 튜토리얼은 Building Your First Network(BYFN) 샘플을 활용하기 때문에 특정 제한이 있습니다 (예 : Fabric CA는 사용하지 않습니다). 따라서 본 튜토리얼의 끝 부분에는 CA, Kafka 클러스터, CouchDB, Zookeeper, vendored chaincode shims 및 Node SDK 클라이언트를 업그레이드하는 방법이 나와 있습니다.

기능 요구 사항에 대한 자세한 내용을 보려면 여기를 클릭 하십시오.

Updating a Channel Configuration

Updating a Channel Configuration(채널 구성 업데이트)

What is a Channel Configuration?(채널 구성이란 무엇입니까?)

채널 구성에는 채널 관리와 관련된 모든 정보가 포함됩니다. 가장 중요한 것은 채널 구성은 채널의 구성원인 조직(org)을 지정하지만 채널 액세스 정책 및 블록 배치 크기와 같은 다른 채널 전체 구성 정보도 포함합니다.

이 구성은 블록의 원장에 저장 되므로 구성(config) 블록이라고합니다. 구성 블록은 단일 구성을 포함합니다. 이 블록 중 첫 번째 블록은 "기원 블록(genesis block)"이라고하며 채널을 부트 스트랩하는 데 필요한 초기 구성을 포함합니다. 채널 구성이 변경될 때마다 새로운 구성 블록을 통해 이루어지며 최신 구성 블록은 현재 채널 구성을 나타냅니다. orerers 및 peers는 새로운 채널을 절단하고 블록 트랜잭션을 검증하는 것과 같은 모든 채널 조작을 용이하게 하기 위해 현재 채널 구성을 메모리에 유지합니다.

구성은 블록으로 저장되기 때문에 구성 업데이트는 "구성 트랜잭션(configuration transaction)"이라는 프로세스를 통해 발생합니다(프로세스가 일반 트랜잭션과 약간 다르긴하지만). 구성 업데이트는 구성을 가져 와서 사람이 읽을 수 있는 형식으로 변환하고 수정한 다음 승인을 위해 제출하는 과정입니다.

설정을 가져 와서 JSON으로 변환하는 프로세스에 대한 자세한 내용은 Adding an Org to a Channel(채널에 조직 추가)를 참조 하십시오. 이 문서에서는 구성을 편집 할 수 있는 여러 가지 방법과 서명을 가져 오는 프로세스에 중점을 둘 것입니다.

Editing a Config(구성 편집)

채널은 구성 가능하지만 무한대 아닙니다. 다른 구성 요소에는 다른 수정 정책(구성 업데이트에 서명하는 데 필요한 ID 그룹 지정)이 있습니다.

변경할 수 있는 범위를 보려면 JSON 형식으로 구성을 보는 것이 중요합니다. Adding an Org to a Channel(채널에 조직 추가) 튜토리얼은 하나를 생성합니다. 따라서 해당 문서를 살펴보면 간단히 참조할 수 있습니다. 그렇지 않은 사용자를 위해 여기에 하나를 제공합니다(가독성을 위해 이 구성을 atom 또는 Visual Studio와 같은 JSON 폴딩을 지원하는 뷰어에 배치하는 것이 도움이 될 수 있음).

{
"channel_group": {
  "groups": {
    "Application": {
      "groups": {
        "Org1MSP": {
          "mod_policy": "Admins",
          "policies": {
            "Admins": {
              "mod_policy": "Admins",
              "policy": {
                "type": 1,
                "value": {
                  "identities": [
                    {
                      "principal": {
                        "msp_identifier": "Org1MSP",
                        "role": "ADMIN"
                      },
                      "principal_classification": "ROLE"
                    }
                  ],
                  "rule": {
                    "n_out_of": {
                      "n": 1,
                      "rules": [
                        {
                          "signed_by": 0
                        }
                      ]
                    }
                  },
                  "version": 0
                }
              },
              "version": "0"
            },
            "Readers": {
              "mod_policy": "Admins",
              "policy": {
                "type": 1,
                "value": {
                  "identities": [
                    {
                      "principal": {
                        "msp_identifier": "Org1MSP",
                        "role": "MEMBER"
                      },
                      "principal_classification": "ROLE"
                    }
                  ],
                  "rule": {
                    "n_out_of": {
                      "n": 1,
                      "rules": [
                        {
                          "signed_by": 0
                        }
                      ]
                    }
                  },
                  "version": 0
                }
              },
              "version": "0"
            },
            "Writers": {
              "mod_policy": "Admins",
              "policy": {
                "type": 1,
                "value": {
                  "identities": [
                    {
                      "principal": {
                        "msp_identifier": "Org1MSP",
                        "role": "MEMBER"
                      },
                      "principal_classification": "ROLE"
                    }
                  ],
                  "rule": {
                    "n_out_of": {
                      "n": 1,
                      "rules": [
                        {
                          "signed_by": 0
                        }
                      ]
                    }
                  },
                  "version": 0
                }
              },
              "version": "0"
            }
          },
          "values": {
            "AnchorPeers": {
              "mod_policy": "Admins",
              "value": {
                "anchor_peers": [
                  {
                    "host": "peer0.org1.example.com",
                    "port": 7051
                  }
                ]
              },
              "version": "0"
            },
            "MSP": {
              "mod_policy": "Admins",
              "value": {
                "config": {
                  "admins": [
                    "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNHRENDQWIrZ0F3SUJBZ0lRSWlyVmg3NVcwWmh0UjEzdmltdmliakFLQmdncWhrak9QUVFEQWpCek1Rc3cKQ1FZRFZRUUdFd0pWVXpFVE1CRUdBMVVFQ0JNS1EyRnNhV1p2Y201cFlURVdNQlFHQTFVRUJ4TU5VMkZ1SUVaeQpZVzVqYVhOamJ6RVpNQmNHQTFVRUNoTVFiM0puTVM1bGVHRnRjR3hsTG1OdmJURWNNQm9HQTFVRUF4TVRZMkV1CmIzSm5NUzVsZUdGdGNHeGxMbU52YlRBZUZ3MHhOekV4TWpreE9USTBNRFphRncweU56RXhNamN4T1RJME1EWmEKTUZzeEN6QUpCZ05WQkFZVEFsVlRNUk13RVFZRFZRUUlFd3BEWVd4cFptOXlibWxoTVJZd0ZBWURWUVFIRXcxVApZVzRnUm5KaGJtTnBjMk52TVI4d0hRWURWUVFEREJaQlpHMXBia0J2Y21jeExtVjRZVzF3YkdVdVkyOXRNRmt3CkV3WUhLb1pJemowQ0FRWUlLb1pJemowREFRY0RRZ0FFNkdVeDlpczZ0aG1ZRE9tMmVHSlA5eW1yaXJYWE1Cd0oKQmVWb1Vpak5haUdsWE03N2NsSE5aZjArMGFjK2djRU5lMzQweGExZVFnb2Q0YjVFcmQrNmtxTk5NRXN3RGdZRApWUjBQQVFIL0JBUURBZ2VBTUF3R0ExVWRFd0VCL3dRQ01BQXdLd1lEVlIwakJDUXdJb0FnWWdoR2xCMjBGWmZCCllQemdYT280czdkU1k1V3NKSkRZbGszTDJvOXZzQ013Q2dZSUtvWkl6ajBFQXdJRFJ3QXdSQUlnYmlEWDVTMlIKRTBNWGRobDZFbmpVNm1lTEJ0eXNMR2ZpZXZWTlNmWW1UQVVDSUdVbnROangrVXZEYkZPRHZFcFRVTm5MUHp0Qwp5ZlBnOEhMdWpMaXVpaWFaCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K"
                  ],
                  "crypto_config": {
                    "identity_identifier_hash_function": "SHA256",
                    "signature_hash_family": "SHA2"
                  },
                  "name": "Org1MSP",
                  "root_certs": [
                    "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNRekNDQWVxZ0F3SUJBZ0lSQU03ZVdTaVM4V3VVM2haMU9tR255eXd3Q2dZSUtvWkl6ajBFQXdJd2N6RUwKTUFrR0ExVUVCaE1DVlZNeEV6QVJCZ05WQkFnVENrTmhiR2xtYjNKdWFXRXhGakFVQmdOVkJBY1REVk5oYmlCRwpjbUZ1WTJselkyOHhHVEFYQmdOVkJBb1RFRzl5WnpFdVpYaGhiWEJzWlM1amIyMHhIREFhQmdOVkJBTVRFMk5oCkxtOXlaekV1WlhoaGJYQnNaUzVqYjIwd0hoY05NVGN4TVRJNU1Ua3lOREEyV2hjTk1qY3hNVEkzTVRreU5EQTIKV2pCek1Rc3dDUVlEVlFRR0V3SlZVekVUTUJFR0ExVUVDQk1LUTJGc2FXWnZjbTVwWVRFV01CUUdBMVVFQnhNTgpVMkZ1SUVaeVlXNWphWE5qYnpFWk1CY0dBMVVFQ2hNUWIzSm5NUzVsZUdGdGNHeGxMbU52YlRFY01Cb0dBMVVFCkF4TVRZMkV1YjNKbk1TNWxlR0Z0Y0d4bExtTnZiVEJaTUJNR0J5cUdTTTQ5QWdFR0NDcUdTTTQ5QXdFSEEwSUEKQkJiTTVZS3B6UmlEbDdLWWFpSDVsVnBIeEl1TDEyaUcyWGhkMHRpbEg3MEljMGFpRUh1dG9rTkZsUXAzTWI0Zgpvb0M2bFVXWnRnRDJwMzZFNThMYkdqK2pYekJkTUE0R0ExVWREd0VCL3dRRUF3SUJwakFQQmdOVkhTVUVDREFHCkJnUlZIU1VBTUE4R0ExVWRFd0VCL3dRRk1BTUJBZjh3S1FZRFZSME9CQ0lFSUdJSVJwUWR0QldYd1dEODRGenEKT0xPM1VtT1ZyQ1NRMkpaTnk5cVBiN0FqTUFvR0NDcUdTTTQ5QkFNQ0EwY0FNRVFDSUdlS2VZL1BsdGlWQTRPSgpRTWdwcDRvaGRMcGxKUFpzNERYS0NuOE9BZG9YQWlCK2g5TFdsR3ZsSDdtNkVpMXVRcDFld2ZESmxsZi9MZXczClgxaDNRY0VMZ3c9PQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg=="
                  ],
                  "tls_root_certs": [
                    "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNTVENDQWZDZ0F3SUJBZ0lSQUtsNEFQWmV6dWt0Nk8wYjRyYjY5Y0F3Q2dZSUtvWkl6ajBFQXdJd2RqRUwKTUFrR0ExVUVCaE1DVlZNeEV6QVJCZ05WQkFnVENrTmhiR2xtYjNKdWFXRXhGakFVQmdOVkJBY1REVk5oYmlCRwpjbUZ1WTJselkyOHhHVEFYQmdOVkJBb1RFRzl5WnpFdVpYaGhiWEJzWlM1amIyMHhIekFkQmdOVkJBTVRGblJzCmMyTmhMbTl5WnpFdVpYaGhiWEJzWlM1amIyMHdIaGNOTVRjeE1USTVNVGt5TkRBMldoY05NamN4TVRJM01Ua3kKTkRBMldqQjJNUXN3Q1FZRFZRUUdFd0pWVXpFVE1CRUdBMVVFQ0JNS1EyRnNhV1p2Y201cFlURVdNQlFHQTFVRQpCeE1OVTJGdUlFWnlZVzVqYVhOamJ6RVpNQmNHQTFVRUNoTVFiM0puTVM1bGVHRnRjR3hsTG1OdmJURWZNQjBHCkExVUVBeE1XZEd4elkyRXViM0puTVM1bGVHRnRjR3hsTG1OdmJUQlpNQk1HQnlxR1NNNDlBZ0VHQ0NxR1NNNDkKQXdFSEEwSUFCSnNpQXVjYlcrM0lqQ2VaaXZPakRiUmFyVlRjTW9TRS9mSnQyU0thR1d5bWQ0am5xM25MWC9vVApCVmpZb21wUG1QbGZ4R0VSWHl0UTNvOVZBL2hwNHBlalh6QmRNQTRHQTFVZER3RUIvd1FFQXdJQnBqQVBCZ05WCkhTVUVDREFHQmdSVkhTVUFNQThHQTFVZEV3RUIvd1FGTUFNQkFmOHdLUVlEVlIwT0JDSUVJSnlqZnFoa0FvY3oKdkRpNnNGSGFZL1Bvd2tPWkxPMHZ0VGdFRnVDbUpFalZNQW9HQ0NxR1NNNDlCQU1DQTBjQU1FUUNJRjVOVVdCVgpmSjgrM0lxU3J1NlFFbjlIa0lsQ0xDMnlvWTlaNHBWMnpBeFNBaUE5NWQzeDhBRXZIcUFNZnIxcXBOWHZ1TW5BCmQzUXBFa1gyWkh3ODZlQlVQZz09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K"
                  ]
                },
                "type": 0
              },
              "version": "0"
            }
          },
          "version": "1"
        },
        "Org2MSP": {
          "mod_policy": "Admins",
          "policies": {
            "Admins": {
              "mod_policy": "Admins",
              "policy": {
                "type": 1,
                "value": {
                  "identities": [
                    {
                      "principal": {
                        "msp_identifier": "Org2MSP",
                        "role": "ADMIN"
                      },
                      "principal_classification": "ROLE"
                    }
                  ],
                  "rule": {
                    "n_out_of": {
                      "n": 1,
                      "rules": [
                        {
                          "signed_by": 0
                        }
                      ]
                    }
                  },
                  "version": 0
                }
              },
              "version": "0"
            },
            "Readers": {
              "mod_policy": "Admins",
              "policy": {
                "type": 1,
                "value": {
                  "identities": [
                    {
                      "principal": {
                        "msp_identifier": "Org2MSP",
                        "role": "MEMBER"
                      },
                      "principal_classification": "ROLE"
                    }
                  ],
                  "rule": {
                    "n_out_of": {
                      "n": 1,
                      "rules": [
                        {
                          "signed_by": 0
                        }
                      ]
                    }
                  },
                  "version": 0
                }
              },
              "version": "0"
            },
            "Writers": {
              "mod_policy": "Admins",
              "policy": {
                "type": 1,
                "value": {
                  "identities": [
                    {
                      "principal": {
                        "msp_identifier": "Org2MSP",
                        "role": "MEMBER"
                      },
                      "principal_classification": "ROLE"
                    }
                  ],
                  "rule": {
                    "n_out_of": {
                      "n": 1,
                      "rules": [
                        {
                          "signed_by": 0
                        }
                      ]
                    }
                  },
                  "version": 0
                }
              },
              "version": "0"
            }
          },
          "values": {
            "AnchorPeers": {
              "mod_policy": "Admins",
              "value": {
                "anchor_peers": [
                  {
                    "host": "peer0.org2.example.com",
                    "port": 7051
                  }
                ]
              },
              "version": "0"
            },
            "MSP": {
              "mod_policy": "Admins",
              "value": {
                "config": {
                  "admins": [
                    "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNHVENDQWNDZ0F3SUJBZ0lSQU5Pb1lIbk9seU94dTJxZFBteStyV293Q2dZSUtvWkl6ajBFQXdJd2N6RUwKTUFrR0ExVUVCaE1DVlZNeEV6QVJCZ05WQkFnVENrTmhiR2xtYjNKdWFXRXhGakFVQmdOVkJBY1REVk5oYmlCRwpjbUZ1WTJselkyOHhHVEFYQmdOVkJBb1RFRzl5WnpJdVpYaGhiWEJzWlM1amIyMHhIREFhQmdOVkJBTVRFMk5oCkxtOXlaekl1WlhoaGJYQnNaUzVqYjIwd0hoY05NVGN4TVRJNU1Ua3lOREEyV2hjTk1qY3hNVEkzTVRreU5EQTIKV2pCYk1Rc3dDUVlEVlFRR0V3SlZVekVUTUJFR0ExVUVDQk1LUTJGc2FXWnZjbTVwWVRFV01CUUdBMVVFQnhNTgpVMkZ1SUVaeVlXNWphWE5qYnpFZk1CMEdBMVVFQXd3V1FXUnRhVzVBYjNKbk1pNWxlR0Z0Y0d4bExtTnZiVEJaCk1CTUdCeXFHU000OUFnRUdDQ3FHU000OUF3RUhBMElBQkh1M0ZWMGlqdFFzckpsbnBCblgyRy9ickFjTHFJSzgKVDFiSWFyZlpvSkhtQm5IVW11RTBhc1dyKzM4VUs0N3hyczNZMGMycGhFVjIvRnhHbHhXMUZubWpUVEJMTUE0RwpBMVVkRHdFQi93UUVBd0lIZ0RBTUJnTlZIUk1CQWY4RUFqQUFNQ3NHQTFVZEl3UWtNQ0tBSU1pSzdteFpnQVVmCmdrN0RPTklXd2F4YktHVGdLSnVSNjZqVmordHZEV3RUTUFvR0NDcUdTTTQ5QkFNQ0EwY0FNRVFDSUQxaEtRdk8KVWxyWmVZMmZZY1N2YWExQmJPM3BVb3NxL2tZVElyaVdVM1J3QWlBR29mWmVPUFByWXVlTlk0Z2JCV2tjc3lpZgpNMkJmeXQwWG9NUThyT2VidUE9PQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg=="
                  ],
                  "crypto_config": {
                    "identity_identifier_hash_function": "SHA256",
                    "signature_hash_family": "SHA2"
                  },
                  "name": "Org2MSP",
                  "root_certs": [
                    "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNSRENDQWVxZ0F3SUJBZ0lSQU1pVXk5SGRSbXB5MDdsSjhRMlZNWXN3Q2dZSUtvWkl6ajBFQXdJd2N6RUwKTUFrR0ExVUVCaE1DVlZNeEV6QVJCZ05WQkFnVENrTmhiR2xtYjNKdWFXRXhGakFVQmdOVkJBY1REVk5oYmlCRwpjbUZ1WTJselkyOHhHVEFYQmdOVkJBb1RFRzl5WnpJdVpYaGhiWEJzWlM1amIyMHhIREFhQmdOVkJBTVRFMk5oCkxtOXlaekl1WlhoaGJYQnNaUzVqYjIwd0hoY05NVGN4TVRJNU1Ua3lOREEyV2hjTk1qY3hNVEkzTVRreU5EQTIKV2pCek1Rc3dDUVlEVlFRR0V3SlZVekVUTUJFR0ExVUVDQk1LUTJGc2FXWnZjbTVwWVRFV01CUUdBMVVFQnhNTgpVMkZ1SUVaeVlXNWphWE5qYnpFWk1CY0dBMVVFQ2hNUWIzSm5NaTVsZUdGdGNHeGxMbU52YlRFY01Cb0dBMVVFCkF4TVRZMkV1YjNKbk1pNWxlR0Z0Y0d4bExtTnZiVEJaTUJNR0J5cUdTTTQ5QWdFR0NDcUdTTTQ5QXdFSEEwSUEKQk50YW1PY1hyaGwrQ2hzYXNSeklNWjV3OHpPWVhGcXhQbGV0a3d5UHJrbHpKWE01Qjl4QkRRVWlWNldJS2tGSwo0Vmd5RlNVWGZqaGdtd25kMUNBVkJXaWpYekJkTUE0R0ExVWREd0VCL3dRRUF3SUJwakFQQmdOVkhTVUVDREFHCkJnUlZIU1VBTUE4R0ExVWRFd0VCL3dRRk1BTUJBZjh3S1FZRFZSME9CQ0lFSU1pSzdteFpnQVVmZ2s3RE9OSVcKd2F4YktHVGdLSnVSNjZqVmordHZEV3RUTUFvR0NDcUdTTTQ5QkFNQ0EwZ0FNRVVDSVFEQ3FFRmFqeU5IQmVaRworOUdWVkNFNWI1YTF5ZlhvS3lkemdLMVgyOTl4ZmdJZ05BSUUvM3JINHFsUE9HbjdSS3Yram9WaUNHS2t6L0F1Cm9FNzI4RWR6WmdRPQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg=="
                  ],
                  "tls_root_certs": [
                    "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNTakNDQWZDZ0F3SUJBZ0lSQU9JNmRWUWMraHBZdkdMSlFQM1YwQU13Q2dZSUtvWkl6ajBFQXdJd2RqRUwKTUFrR0ExVUVCaE1DVlZNeEV6QVJCZ05WQkFnVENrTmhiR2xtYjNKdWFXRXhGakFVQmdOVkJBY1REVk5oYmlCRwpjbUZ1WTJselkyOHhHVEFYQmdOVkJBb1RFRzl5WnpJdVpYaGhiWEJzWlM1amIyMHhIekFkQmdOVkJBTVRGblJzCmMyTmhMbTl5WnpJdVpYaGhiWEJzWlM1amIyMHdIaGNOTVRjeE1USTVNVGt5TkRBMldoY05NamN4TVRJM01Ua3kKTkRBMldqQjJNUXN3Q1FZRFZRUUdFd0pWVXpFVE1CRUdBMVVFQ0JNS1EyRnNhV1p2Y201cFlURVdNQlFHQTFVRQpCeE1OVTJGdUlFWnlZVzVqYVhOamJ6RVpNQmNHQTFVRUNoTVFiM0puTWk1bGVHRnRjR3hsTG1OdmJURWZNQjBHCkExVUVBeE1XZEd4elkyRXViM0puTWk1bGVHRnRjR3hsTG1OdmJUQlpNQk1HQnlxR1NNNDlBZ0VHQ0NxR1NNNDkKQXdFSEEwSUFCTWZ1QTMwQVVBT1ZKRG1qVlBZd1lNbTlweW92MFN6OHY4SUQ5N0twSHhXOHVOOUdSOU84aVdFMgo5bllWWVpiZFB2V1h1RCszblpweUFNcGZja3YvYUV5alh6QmRNQTRHQTFVZER3RUIvd1FFQXdJQnBqQVBCZ05WCkhTVUVDREFHQmdSVkhTVUFNQThHQTFVZEV3RUIvd1FGTUFNQkFmOHdLUVlEVlIwT0JDSUVJRnk5VHBHcStQL08KUGRXbkZXdWRPTnFqVDRxOEVKcDJmbERnVCtFV2RnRnFNQW9HQ0NxR1NNNDlCQU1DQTBnQU1FVUNJUUNZYlhSeApXWDZoUitPU0xBNSs4bFRwcXRMWnNhOHVuS3J3ek1UYXlQUXNVd0lnVSs5YXdaaE0xRzg3bGE0V0h4cmt5eVZ2CkU4S1ZsR09IVHVPWm9TMU5PT0U9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K"
                  ]
                },
                "type": 0
              },
              "version": "0"
            }
          },
          "version": "1"
        },
        "Org3MSP": {
          "groups": {},
          "mod_policy": "Admins",
          "policies": {
            "Admins": {
              "mod_policy": "Admins",
              "policy": {
                "type": 1,
                "value": {
                  "identities": [
                    {
                      "principal": {
                        "msp_identifier": "Org3MSP",
                        "role": "ADMIN"
                      },
                      "principal_classification": "ROLE"
                    }
                  ],
                  "rule": {
                    "n_out_of": {
                      "n": 1,
                      "rules": [
                        {
                          "signed_by": 0
                        }
                      ]
                    }
                  },
                  "version": 0
                }
              },
              "version": "0"
            },
            "Readers": {
              "mod_policy": "Admins",
              "policy": {
                "type": 1,
                "value": {
                  "identities": [
                    {
                      "principal": {
                        "msp_identifier": "Org3MSP",
                        "role": "MEMBER"
                      },
                      "principal_classification": "ROLE"
                    }
                  ],
                  "rule": {
                    "n_out_of": {
                      "n": 1,
                      "rules": [
                        {
                          "signed_by": 0
                        }
                      ]
                    }
                  },
                  "version": 0
                }
              },
              "version": "0"
            },
            "Writers": {
              "mod_policy": "Admins",
              "policy": {
                "type": 1,
                "value": {
                  "identities": [
                    {
                      "principal": {
                        "msp_identifier": "Org3MSP",
                        "role": "MEMBER"
                      },
                      "principal_classification": "ROLE"
                    }
                  ],
                  "rule": {
                    "n_out_of": {
                      "n": 1,
                      "rules": [
                        {
                          "signed_by": 0
                        }
                      ]
                    }
                  },
                  "version": 0
                }
              },
              "version": "0"
            }
          },
          "values": {
            "MSP": {
              "mod_policy": "Admins",
              "value": {
                "config": {
                  "admins": [
                    "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNHRENDQWIrZ0F3SUJBZ0lRQUlSNWN4U0hpVm1kSm9uY3FJVUxXekFLQmdncWhrak9QUVFEQWpCek1Rc3cKQ1FZRFZRUUdFd0pWVXpFVE1CRUdBMVVFQ0JNS1EyRnNhV1p2Y201cFlURVdNQlFHQTFVRUJ4TU5VMkZ1SUVaeQpZVzVqYVhOamJ6RVpNQmNHQTFVRUNoTVFiM0puTXk1bGVHRnRjR3hsTG1OdmJURWNNQm9HQTFVRUF4TVRZMkV1CmIzSm5NeTVsZUdGdGNHeGxMbU52YlRBZUZ3MHhOekV4TWpreE9UTTRNekJhRncweU56RXhNamN4T1RNNE16QmEKTUZzeEN6QUpCZ05WQkFZVEFsVlRNUk13RVFZRFZRUUlFd3BEWVd4cFptOXlibWxoTVJZd0ZBWURWUVFIRXcxVApZVzRnUm5KaGJtTnBjMk52TVI4d0hRWURWUVFEREJaQlpHMXBia0J2Y21jekxtVjRZVzF3YkdVdVkyOXRNRmt3CkV3WUhLb1pJemowQ0FRWUlLb1pJemowREFRY0RRZ0FFSFlkVFY2ZC80cmR4WFd2cm1qZ0hIQlhXc2lxUWxrcnQKZ0p1NzMxcG0yZDRrWU82aEd2b2tFRFBwbkZFdFBwdkw3K1F1UjhYdkFQM0tqTkt0NHdMRG5hTk5NRXN3RGdZRApWUjBQQVFIL0JBUURBZ2VBTUF3R0ExVWRFd0VCL3dRQ01BQXdLd1lEVlIwakJDUXdJb0FnSWNxUFVhM1VQNmN0Ck9LZmYvKzVpMWJZVUZFeVFlMVAyU0hBRldWSWUxYzB3Q2dZSUtvWkl6ajBFQXdJRFJ3QXdSQUlnUm5LRnhsTlYKSmppVGpkZmVoczRwNy9qMkt3bFVuUWVuNFkyUnV6QjFrbm9DSUd3dEZ1TEdpRFY2THZSL2pHVXR3UkNyeGw5ZApVNENCeDhGbjBMdXNMTkJYCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K"
                  ],
                  "crypto_config": {
                    "identity_identifier_hash_function": "SHA256",
                    "signature_hash_family": "SHA2"
                  },
                  "name": "Org3MSP",
                  "root_certs": [
                    "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNRakNDQWVtZ0F3SUJBZ0lRUkN1U2Y0RVJNaDdHQW1ydTFIQ2FZREFLQmdncWhrak9QUVFEQWpCek1Rc3cKQ1FZRFZRUUdFd0pWVXpFVE1CRUdBMVVFQ0JNS1EyRnNhV1p2Y201cFlURVdNQlFHQTFVRUJ4TU5VMkZ1SUVaeQpZVzVqYVhOamJ6RVpNQmNHQTFVRUNoTVFiM0puTXk1bGVHRnRjR3hsTG1OdmJURWNNQm9HQTFVRUF4TVRZMkV1CmIzSm5NeTVsZUdGdGNHeGxMbU52YlRBZUZ3MHhOekV4TWpreE9UTTRNekJhRncweU56RXhNamN4T1RNNE16QmEKTUhNeEN6QUpCZ05WQkFZVEFsVlRNUk13RVFZRFZRUUlFd3BEWVd4cFptOXlibWxoTVJZd0ZBWURWUVFIRXcxVApZVzRnUm5KaGJtTnBjMk52TVJrd0Z3WURWUVFLRXhCdmNtY3pMbVY0WVcxd2JHVXVZMjl0TVJ3d0dnWURWUVFECkV4TmpZUzV2Y21jekxtVjRZVzF3YkdVdVkyOXRNRmt3RXdZSEtvWkl6ajBDQVFZSUtvWkl6ajBEQVFjRFFnQUUKZXFxOFFQMnllM08vM1J3UzI0SWdtRVdST3RnK3Zyc2pRY1BvTU42NEZiUGJKbmExMklNaVdDUTF6ZEZiTU9hSAorMUlrb21yY0RDL1ZpejkvY0M0NW9xTmZNRjB3RGdZRFZSMFBBUUgvQkFRREFnR21NQThHQTFVZEpRUUlNQVlHCkJGVWRKUUF3RHdZRFZSMFRBUUgvQkFVd0F3RUIvekFwQmdOVkhRNEVJZ1FnSWNxUFVhM1VQNmN0T0tmZi8rNWkKMWJZVUZFeVFlMVAyU0hBRldWSWUxYzB3Q2dZSUtvWkl6ajBFQXdJRFJ3QXdSQUlnTEgxL2xSZElWTVA4Z2FWeQpKRW01QWQ0SjhwZ256N1BVV2JIMzZvdVg4K1lDSUNPK20vUG9DbDRIbTlFbXhFN3ZnUHlOY2trVWd0SlRiTFhqCk5SWjBxNTdWCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K"
                  ],
                  "tls_root_certs": [
                    "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNTVENDQWZDZ0F3SUJBZ0lSQU9xc2JQQzFOVHJzclEvUUNpalh6K0F3Q2dZSUtvWkl6ajBFQXdJd2RqRUwKTUFrR0ExVUVCaE1DVlZNeEV6QVJCZ05WQkFnVENrTmhiR2xtYjNKdWFXRXhGakFVQmdOVkJBY1REVk5oYmlCRwpjbUZ1WTJselkyOHhHVEFYQmdOVkJBb1RFRzl5WnpNdVpYaGhiWEJzWlM1amIyMHhIekFkQmdOVkJBTVRGblJzCmMyTmhMbTl5WnpNdVpYaGhiWEJzWlM1amIyMHdIaGNOTVRjeE1USTVNVGt6T0RNd1doY05NamN4TVRJM01Ua3oKT0RNd1dqQjJNUXN3Q1FZRFZRUUdFd0pWVXpFVE1CRUdBMVVFQ0JNS1EyRnNhV1p2Y201cFlURVdNQlFHQTFVRQpCeE1OVTJGdUlFWnlZVzVqYVhOamJ6RVpNQmNHQTFVRUNoTVFiM0puTXk1bGVHRnRjR3hsTG1OdmJURWZNQjBHCkExVUVBeE1XZEd4elkyRXViM0puTXk1bGVHRnRjR3hsTG1OdmJUQlpNQk1HQnlxR1NNNDlBZ0VHQ0NxR1NNNDkKQXdFSEEwSUFCSVJTTHdDejdyWENiY0VLMmhxSnhBVm9DaDhkejNqcnA5RHMyYW9TQjBVNTZkSUZhVmZoR2FsKwovdGp6YXlndXpFalFhNlJ1MmhQVnRGM2NvQnJ2Ulpxalh6QmRNQTRHQTFVZER3RUIvd1FFQXdJQnBqQVBCZ05WCkhTVUVDREFHQmdSVkhTVUFNQThHQTFVZEV3RUIvd1FGTUFNQkFmOHdLUVlEVlIwT0JDSUVJQ2FkVERGa0JPTGkKblcrN2xCbDExL3pPbXk4a1BlYXc0MVNZWEF6cVhnZEVNQW9HQ0NxR1NNNDlCQU1DQTBjQU1FUUNJQlgyMWR3UwpGaG5NdDhHWXUweEgrUGd5aXQreFdQUjBuTE1Jc1p2dVlRaktBaUFLUlE5N2VrLzRDTzZPWUtSakR0VFM4UFRmCm9nTmJ6dTBxcThjbVhseW5jZz09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K"
                  ]
                },
                "type": 0
              },
              "version": "0"
            }
          },
          "version": "0"
        }
      },
      "mod_policy": "Admins",
      "policies": {
        "Admins": {
          "mod_policy": "Admins",
          "policy": {
            "type": 3,
            "value": {
              "rule": "MAJORITY",
              "sub_policy": "Admins"
            }
          },
          "version": "0"
        },
        "Readers": {
          "mod_policy": "Admins",
          "policy": {
            "type": 3,
            "value": {
              "rule": "ANY",
              "sub_policy": "Readers"
            }
          },
          "version": "0"
        },
        "Writers": {
          "mod_policy": "Admins",
          "policy": {
            "type": 3,
            "value": {
              "rule": "ANY",
              "sub_policy": "Writers"
            }
          },
          "version": "0"
        }
      },
      "version": "1"
    },
    "Orderer": {
      "groups": {
        "OrdererOrg": {
          "mod_policy": "Admins",
          "policies": {
            "Admins": {
              "mod_policy": "Admins",
              "policy": {
                "type": 1,
                "value": {
                  "identities": [
                    {
                      "principal": {
                        "msp_identifier": "OrdererMSP",
                        "role": "ADMIN"
                      },
                      "principal_classification": "ROLE"
                    }
                  ],
                  "rule": {
                    "n_out_of": {
                      "n": 1,
                      "rules": [
                        {
                          "signed_by": 0
                        }
                      ]
                    }
                  },
                  "version": 0
                }
              },
              "version": "0"
            },
            "Readers": {
              "mod_policy": "Admins",
              "policy": {
                "type": 1,
                "value": {
                  "identities": [
                    {
                      "principal": {
                        "msp_identifier": "OrdererMSP",
                        "role": "MEMBER"
                      },
                      "principal_classification": "ROLE"
                    }
                  ],
                  "rule": {
                    "n_out_of": {
                      "n": 1,
                      "rules": [
                        {
                          "signed_by": 0
                        }
                      ]
                    }
                  },
                  "version": 0
                }
              },
              "version": "0"
            },
            "Writers": {
              "mod_policy": "Admins",
              "policy": {
                "type": 1,
                "value": {
                  "identities": [
                    {
                      "principal": {
                        "msp_identifier": "OrdererMSP",
                        "role": "MEMBER"
                      },
                      "principal_classification": "ROLE"
                    }
                  ],
                  "rule": {
                    "n_out_of": {
                      "n": 1,
                      "rules": [
                        {
                          "signed_by": 0
                        }
                      ]
                    }
                  },
                  "version": 0
                }
              },
              "version": "0"
            }
          },
          "values": {
            "MSP": {
              "mod_policy": "Admins",
              "value": {
                "config": {
                  "admins": [
                    "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNDakNDQWJDZ0F3SUJBZ0lRSFNTTnIyMWRLTTB6THZ0dEdoQnpMVEFLQmdncWhrak9QUVFEQWpCcE1Rc3cKQ1FZRFZRUUdFd0pWVXpFVE1CRUdBMVVFQ0JNS1EyRnNhV1p2Y201cFlURVdNQlFHQTFVRUJ4TU5VMkZ1SUVaeQpZVzVqYVhOamJ6RVVNQklHQTFVRUNoTUxaWGhoYlhCc1pTNWpiMjB4RnpBVkJnTlZCQU1URG1OaExtVjRZVzF3CmJHVXVZMjl0TUI0WERURTNNVEV5T1RFNU1qUXdObG9YRFRJM01URXlOekU1TWpRd05sb3dWakVMTUFrR0ExVUUKQmhNQ1ZWTXhFekFSQmdOVkJBZ1RDa05oYkdsbWIzSnVhV0V4RmpBVUJnTlZCQWNURFZOaGJpQkdjbUZ1WTJsegpZMjh4R2pBWUJnTlZCQU1NRVVGa2JXbHVRR1Y0WVcxd2JHVXVZMjl0TUZrd0V3WUhLb1pJemowQ0FRWUlLb1pJCnpqMERBUWNEUWdBRTZCTVcvY0RGUkUvakFSenV5N1BjeFQ5a3pnZitudXdwKzhzK2xia0hZd0ZpaForMWRhR3gKKzhpS1hDY0YrZ0tpcVBEQXBpZ2REOXNSeTBoTEMwQnRacU5OTUVzd0RnWURWUjBQQVFIL0JBUURBZ2VBTUF3RwpBMVVkRXdFQi93UUNNQUF3S3dZRFZSMGpCQ1F3SW9BZ3o3bDQ2ZXRrODU0NFJEanZENVB6YjV3TzI5N0lIMnNUCngwTjAzOHZibkpzd0NnWUlLb1pJemowRUF3SURTQUF3UlFJaEFNRTJPWXljSnVyYzhVY2hkeTA5RU50RTNFUDIKcVoxSnFTOWVCK0gxSG5FSkFpQUtXa2h5TmI0akRPS2MramJIVmgwV0YrZ3J4UlJYT1hGaEl4ei85elI3UUE9PQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg=="
                  ],
                  "crypto_config": {
                    "identity_identifier_hash_function": "SHA256",
                    "signature_hash_family": "SHA2"
                  },
                  "name": "OrdererMSP",
                  "root_certs": [
                    "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNMakNDQWRXZ0F3SUJBZ0lRY2cxUVZkVmU2Skd6YVU1cmxjcW4vakFLQmdncWhrak9QUVFEQWpCcE1Rc3cKQ1FZRFZRUUdFd0pWVXpFVE1CRUdBMVVFQ0JNS1EyRnNhV1p2Y201cFlURVdNQlFHQTFVRUJ4TU5VMkZ1SUVaeQpZVzVqYVhOamJ6RVVNQklHQTFVRUNoTUxaWGhoYlhCc1pTNWpiMjB4RnpBVkJnTlZCQU1URG1OaExtVjRZVzF3CmJHVXVZMjl0TUI0WERURTNNVEV5T1RFNU1qUXdObG9YRFRJM01URXlOekU1TWpRd05sb3dhVEVMTUFrR0ExVUUKQmhNQ1ZWTXhFekFSQmdOVkJBZ1RDa05oYkdsbWIzSnVhV0V4RmpBVUJnTlZCQWNURFZOaGJpQkdjbUZ1WTJsegpZMjh4RkRBU0JnTlZCQW9UQzJWNFlXMXdiR1V1WTI5dE1SY3dGUVlEVlFRREV3NWpZUzVsZUdGdGNHeGxMbU52CmJUQlpNQk1HQnlxR1NNNDlBZ0VHQ0NxR1NNNDlBd0VIQTBJQUJQTVI2MGdCcVJham9hS0U1TExRYjRIb28wN3QKYTRuM21Ncy9NRGloQVQ5YUN4UGZBcDM5SS8wMmwvZ2xiMTdCcEtxZGpGd0JKZHNuMVN6ZnQ3NlZkTitqWHpCZApNQTRHQTFVZER3RUIvd1FFQXdJQnBqQVBCZ05WSFNVRUNEQUdCZ1JWSFNVQU1BOEdBMVVkRXdFQi93UUZNQU1CCkFmOHdLUVlEVlIwT0JDSUVJTSs1ZU9uclpQT2VPRVE0N3crVDgyK2NEdHZleUI5ckU4ZERkTi9MMjV5Yk1Bb0cKQ0NxR1NNNDlCQU1DQTBjQU1FUUNJQVB6SGNOUmQ2a3QxSEdpWEFDclFTM0grL3R5NmcvVFpJa1pTeXIybmdLNQpBaUJnb1BVTTEwTHNsMVFtb2dlbFBjblZGZjJoODBXR2I3NGRIS2tzVFJKUkx3PT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo="
                  ],
                  "tls_root_certs": [
                    "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNORENDQWR1Z0F3SUJBZ0lRYWJ5SUl6cldtUFNzSjJacisvRVpXVEFLQmdncWhrak9QUVFEQWpCc01Rc3cKQ1FZRFZRUUdFd0pWVXpFVE1CRUdBMVVFQ0JNS1EyRnNhV1p2Y201cFlURVdNQlFHQTFVRUJ4TU5VMkZ1SUVaeQpZVzVqYVhOamJ6RVVNQklHQTFVRUNoTUxaWGhoYlhCc1pTNWpiMjB4R2pBWUJnTlZCQU1URVhSc2MyTmhMbVY0CllXMXdiR1V1WTI5dE1CNFhEVEUzTVRFeU9URTVNalF3TmxvWERUSTNNVEV5TnpFNU1qUXdObG93YkRFTE1Ba0cKQTFVRUJoTUNWVk14RXpBUkJnTlZCQWdUQ2tOaGJHbG1iM0p1YVdFeEZqQVVCZ05WQkFjVERWTmhiaUJHY21GdQpZMmx6WTI4eEZEQVNCZ05WQkFvVEMyVjRZVzF3YkdVdVkyOXRNUm93R0FZRFZRUURFeEYwYkhOallTNWxlR0Z0CmNHeGxMbU52YlRCWk1CTUdCeXFHU000OUFnRUdDQ3FHU000OUF3RUhBMElBQkVZVE9mdG1rTHdiSlRNeG1aVzMKZVdqRUQ2eW1UeEhYeWFQdTM2Y1NQWDlldDZyU3Y5UFpCTGxyK3hZN1dtYlhyOHM5K3E1RDMwWHl6OEh1OWthMQpSc1dqWHpCZE1BNEdBMVVkRHdFQi93UUVBd0lCcGpBUEJnTlZIU1VFQ0RBR0JnUlZIU1VBTUE4R0ExVWRFd0VCCi93UUZNQU1CQWY4d0tRWURWUjBPQkNJRUlJcjduNTVjTWlUdENEYmM5UGU0RFpnZ0ZYdHV2RktTdnBNYUhzbzAKSnpFd01Bb0dDQ3FHU000OUJBTUNBMGNBTUVRQ0lGM1gvMGtQRkFVQzV2N25JVVh6SmI5Z3JscWxET05UeVg2QQpvcmtFVTdWb0FpQkpMbS9IUFZ0aVRHY2NldUZPZTE4SnNwd0JTZ1hxNnY1K1BobEdsbU9pWHc9PQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg=="
                  ]
                },
                "type": 0
              },
              "version": "0"
            }
          },
          "version": "0"
        }
      },
      "mod_policy": "Admins",
      "policies": {
        "Admins": {
          "mod_policy": "Admins",
          "policy": {
            "type": 3,
            "value": {
              "rule": "MAJORITY",
              "sub_policy": "Admins"
            }
          },
          "version": "0"
        },
        "BlockValidation": {
          "mod_policy": "Admins",
          "policy": {
            "type": 3,
            "value": {
              "rule": "ANY",
              "sub_policy": "Writers"
            }
          },
          "version": "0"
        },
        "Readers": {
          "mod_policy": "Admins",
          "policy": {
            "type": 3,
            "value": {
              "rule": "ANY",
              "sub_policy": "Readers"
            }
          },
          "version": "0"
        },
        "Writers": {
          "mod_policy": "Admins",
          "policy": {
            "type": 3,
            "value": {
              "rule": "ANY",
              "sub_policy": "Writers"
            }
          },
          "version": "0"
        }
      },
      "values": {
        "BatchSize": {
          "mod_policy": "Admins",
          "value": {
            "absolute_max_bytes": 103809024,
            "max_message_count": 10,
            "preferred_max_bytes": 524288
          },
          "version": "0"
        },
        "BatchTimeout": {
          "mod_policy": "Admins",
          "value": {
            "timeout": "2s"
          },
          "version": "0"
        },
        "ChannelRestrictions": {
          "mod_policy": "Admins",
          "version": "0"
        },
        "ConsensusType": {
          "mod_policy": "Admins",
          "value": {
            "type": "solo"
          },
          "version": "0"
        }
      },
      "version": "0"
    }
  },
  "mod_policy": "",
  "policies": {
    "Admins": {
      "mod_policy": "Admins",
      "policy": {
        "type": 3,
        "value": {
          "rule": "MAJORITY",
          "sub_policy": "Admins"
        }
      },
      "version": "0"
    },
    "Readers": {
      "mod_policy": "Admins",
      "policy": {
        "type": 3,
        "value": {
          "rule": "ANY",
          "sub_policy": "Readers"
        }
      },
      "version": "0"
    },
    "Writers": {
      "mod_policy": "Admins",
      "policy": {
        "type": 3,
        "value": {
          "rule": "ANY",
          "sub_policy": "Writers"
        }
      },
      "version": "0"
    }
  },
  "values": {
    "BlockDataHashingStructure": {
      "mod_policy": "Admins",
      "value": {
        "width": 4294967295
      },
      "version": "0"
    },
    "Consortium": {
      "mod_policy": "Admins",
      "value": {
        "name": "SampleConsortium"
      },
      "version": "0"
    },
    "HashingAlgorithm": {
      "mod_policy": "Admins",
      "value": {
        "name": "SHA256"
      },
      "version": "0"
    },
    "OrdererAddresses": {
      "mod_policy": "/Channel/Orderer/Admins",
      "value": {
        "addresses": [
          "orderer.example.com:7050"
        ]
      },
      "version": "0"
    }
  },
  "version": "0"
},
"sequence": "3",
"type": 0
}

설정은 이 형식으로 위협적으로 보일지 모르지만 일단 그것을 공부하면 논리 구조가 있음을 알 수 있습니다.

채널 수준에서 특정 작업을 수행 할 수 있는 사람을 정의하고 구성 채널을 변경할 수 있는 사람을 변경할 권한이 있는 정책의 정의 외에도 구성 업데이트를 사용하여 수정할 수 있는 다른 종류의 기능이 있습니다. Adding an Org to a Channel(채널에 조직 추가) 과정은 채널을 조직에 추가하는 등 가장 중요한 작업 중 하나를 수행할 수 있습니다. 구성 업데이트로 변경할 수 있는 몇 가지 다른 사항은 다음과 같습니다.

  • Batch Size. 이 매개 변수는 블록의 트랜잭션 수와 크기를 지정합니다. 블록은 absolute_max_bytes보다 크거나 블록 내에  max_message_count개 이상의 트랜잭션 보다 많게 표시되지 않습니다. preferred_max_bytes 아래에 블록을 구성할 수 있으면 블록이 너무 일찍 절단되고 이 크기보다 큰 트랜잭션은 자체 블록에 나타납니다. { "absolute_max_bytes" : 102760448 , "max_message_count" : 10 , "preferred_max_bytes" : 524288 }
  • Batch Timeout. 블록을 절단하기 전에 추가 트랜잭션을 위해 첫 번째 트랜잭션이 도착한 후에 기다리는 시간입니다. 이 값을 줄이면 대기 시간이 향상되지만 블록을 너무 많이 줄이면 블록이 최대 용량까지 채우지 못해 처리량이 감소 할 수 있습니다. { "timeout" : "2s" }
  • Channel Restrictions. orderer가 할당하고자하는 총 채널 수는 max_count로 지정할 수 있습니다. 이는 주로 컨소시엄 ChannelCreation 정책이 약한 사전 제작 환경에서 유용합니다 . { "max_count" : 1000 }
  • Channel Creation Policy. 채널이 정의된 컨소시엄에 대한 새 채널의 Application 그룹에 대한 mod_policy로 설정될 정책 값을 정의합니다. 채널 생성 요청에 첨부된 시그니처 세트는 새 채널에서 이 정책의 인스턴스화와 비교하여 점검되어 채널 생성이 승인된 것입니다. 이 구성 value는 orerer 시스템 채널에서만 설정됩니다. { "type": 3, "value": { "rule": "ANY", "sub_policy": "Admins" } }
  • Kafka brokers. ConsensusTypekafka로 설정되면 brokers 목록은 시작 시 주문자가 처음에 연결할 Kafka brokers의 일부 하위 집합 (또는 모든 가능한 집합)을 열거합니다. 기원 블록(genesis block)이 부트스트랩(bootstrapping)되는 동안 컨센서스 유형을 변경하는 것은 불가능합니다. { "brokers": [ "kafka0:9092", "kafka1:9092", "kafka2:9092", "kafka3:9092" ] }
  • Anchor Peers Definition. 각 조직(Org)에 대한 앵커 피어의 위치를 정의합니다. { "host": "peer0.org2.example.com", "port": 7051 }
  • Hashing Structure. 블록 데이터는 바이트 배열들의 배열입니다. 블록 데이터의 해시는 Merkle 트리로 계산됩니다. 이 값은 해당 Merkle 트리의 너비를 지정합니다. 당분간, 이 값은 4294967295 블록 데이터 바이트의 연결에 대한 단순한 평면 해시에 해당하는 값으로 고정됩니다. { "width": 4294967295 }
  • Hashing Algorithm. 블록 체인의 블록으로 인코딩된 해시 값을 계산하는 데 사용하는 알고리즘입니다. 특히 이것은 데이터 해시와 이전 블록 해시 필드에 영향을 줍니다. 이 필드에는 현재 하나의 유효한 값(SHA256)만 있으므로 변경해서는 안됩니다. { "name": "SHA256" }
  • Block Validation. 이 정책은 블록이 유효하다고 판단되는 서명 요구사항을 지정합니다. 기본적으로 주문 조직(ordering org)의 일부 회원이 서명해야 합니다. { "type": 3, "value": { "rule": "ANY", "sub_policy": "Writers" } }
  • Orderer Address. 클라이언트가 orderer Broadcast and Deliver 기능을 호출할 수 있는 주소 목록. 피어(Peer)는 이러한 주소들 사이에서 무작위로 선택하고 블록 검색을 위해 두 주소 사이에서 장애 조치를 수행합니다. { "addresses": [ "orderer.example.com:7050" ] }

Org에 아티팩트 및 MSP 정보를 추가하는 것 처럼 프로세스를 되돌려 제거할 수 있습니다.

Note 합의 형태가 정의된 네트워크가 부트스트랩 된 후에, 그 구성 업데이트를 통해 변화시킬 수 없는 것이다.

Capability Requirements(역량 요구사항) 으로 알려진 또 다른 중요한 채널 구성(특히 v1.1의 경우)이 있습니다. 그것은 여기에서 문서를 찾을 수 있습니다.

채널의 블록 일괄 처리 크기(block batch size)를 편집하고자 한다고 가정해봅시다(단일 숫자 필드이기 때문에 가장 쉬운 변경사항 중 하나입니다). 먼저 JSON 경로를 쉽게 참조할 수 있도록 환경 변수로 정의합니다.

이것을 설정하려면 설정을 살펴보고 원하는 것을 찾은 다음 경로를 추적하십시오.

예를 들어 batch size를 찾으면 Orderervalue라는 것을 알 수 있습니다. Ordererchannel_group 아래에 있는 groups 안에 있습니다. batch size 값은 max_message_countvalue 값 아래의 매개변수를 갖습니다.

어떤 경로를 만들 것입니다 :

 export MAXBATCHSIZEPATH=".channel_group.groups.Orderer.values.BatchSize.value.max_message_count"

그런 다음 해당 속성의 값을 표시합니다 :

jq "$MAXBATCHSIZEPATH" config.jsonWich should return a value of 10 (in our sample network at least).

10의 값을 반환해야 합니다(최소한의 샘플 네트워크에서).

이제 새 batch size를 설정하고 새 값을 표시합니다.

 jq “$MAXBATCHSIZEPATH = 20” config.json > modified_config.json
 jq “$MAXBATCHSIZEPATH” modified_config.json

JSON을 수정하면 변환 및 제출할 준비가 완료됩니다. Adding an Org to a Channel(채널에 조직 추가)의 스크립트와 단계는 JSON 변환 프로세스를 안내합니다. 따라서 제출(submmitting) 프로세스를 살펴보겠습니다.

Get the Necessary Signatures

protobuf 파일을 성공적으로 생성했으면 서명을 해야 합니다. 이렇게 하려면 변경하려고 하는 모든 정책에 대한 관련 정책을 알아야합니다.

기본적으로 다음 구성을 편집합니다 :

  • A particular org (예 : 앵커 피어 변경)에는 해당 조직의 admin 서명만 있으면 됩니다.
  • The application (회원 조직이 누구인지)는 application 조직의 admin과 대다수가 서명해야 합니다.
  • The orderer 는 대부분 ordering 조직의 admin(기본값은 1명)만 필요합니다.
  • The top level channel group 은 대다수의 application 조직 admin과 orderer 조직 admin의 동의가 필요합니다.

채널의 기본 정책을 변경한 경우 이에 따라 서명 요구 사항을 계산해야합니다.

참고 : 응용 프로그램에 따라 서명 컬렉션을 스크립팅 할 수 있습니다. 일반적으로 필요한 것보다 더 많은 서명을 수집 할 수 있습니다.

이러한 서명을 얻는 실제 프로세스는 시스템을 설정한 방법에 따라 다르지만 두 가지 주요 구현이 있습니다. 현재 패브릭 명령 줄의 기본값은 "pass it along" 시스템입니다. 즉, 조직의 Admin이 구성 업데이트를 제안하면 서명해야하는 다른 사람 (일반적으로 다른 Admin)에게 업데이트를 보냅니다. 이 Admin은 서명 (또는 서명하지 않음) 한 후 다음 Admin에게 전달하며, 구성을 제출하기에 충분한 서명이있을 때까지 계속합니다.

이것은 단순성 덕분입니다. 충분한 서명이 있을 때 마지막 Admin은 config 트랜잭션을 제출하기 만하면됩니다 (Fabric에서는 peer channel update 명령이 기본적으로 서명을 포함합니다). 그러나 이 과정은 작은 채널에서만 실용적일 것입니다. 왜냐하면 "pass it along" 방법은 시간이 오래 걸릴 수 있기 때문입니다.

다른 옵션은 채널의 모든 Admin에게 업데이트를 제출하고 충분한 서명이 다시 오기를 기다리는 것입니다. 이 서명들은 함께 꿰매어 제출할 수 있습니다. 이로 인해 구성 업데이트를 만든 Admin(서명자 당 파일을 처리해야 함)에게는 다소 어려움이 있지만 Fabric 관리 응용 프로그램을 개발하는 사용자에게는 권장되는 워크 플로입니다.

설정이 원장에 추가되면 모든 것을 올바르게 추가했는지 확인하기 위해 pull 해서 JSON으로 변환하는 것이 가장 좋습니다. 이것은 최신 설정의 유용한 복사본으로도 사용됩니다.

Membership Service Providers (MSP)

Membership Service Providers (MSP)

이 문서는 MSP의 설정 및 모범 사례에 대한 세부 정보를 제공합니다.

멤버쉽 서비스 공급자(MSP)는 멤버십 운영 아키텍처의 추상화를 제공하는 것을 목표로하는 구성 요소입니다.

특히 MSP는 인증서 발급 및 유효성 검사 및 사용자 인증에 대한 모든 암호화 메커니즘 및 프로토콜을 추상화합니다. MSP는 자신의 신원 개념과 신원을 관리 (신원 확인) 및 인증 (서명 생성 및 검증)하는 규칙을 정의 할 수 있습니다.

Hyperledger 패브릭 블록 체인 네트워크는 하나 이상의 MSP에 의해 관리 될 수 있습니다. 이는 멤버쉽 작업의 모듈화와 다양한 멤버쉽 표준 및 아키텍처 간의 상호 운용성을 제공합니다.

이 문서의 나머지 부분에서는 Hyperledger Fabric에서 지원하는 MSP 구현의 설정에 대해 자세히 설명하고 그 사용과 관련된 모범 사례에 대해 논의합니다.

MSP 구성

MSP의 인스턴스를 설정하려면 Peer 및 Orderer 서명을 가능하게하기 위해 각 Peer 및 Orderer에게 로컬로 구성을 지정하고 Peer, Orderer, 클라이언트 ID 유효성 검사 및 각 서명 확인을 가능하게 하는 채널에서 구성을 지정해야합니다 (인증 ) 모든 채널 회원에 의해.

우선, 각각의 MSP에 대한 이름이 네트워크에 해당 MSP를 참조하기 위해 지정 될 필요 (예를 들어 msp1org2 및 org3.divA). 컨소시엄, 조직 또는 조직 부서를 대표하는 MSP의 멤버십 규칙을 채널에서 참조하는 이름입니다. 이를 MSP Identifier 또는 MSP ID 라고도합니다 . MSP 식별자는 MSP 인스턴스별로 고유해야합니다. 예를 들어, 동일한 식별자를 가진 두 개의 MSP 인스턴스가 시스템 채널 genesis에서 탐지되어야합니다. Orderer 설정은 실패합니다.

MSP의 기본 구현의 경우 ID (인증서) 유효성 검사 및 서명 확인을 허용하기 위해 일련의 매개 변수를 지정해야합니다. 이 매개 변수는 RFC5280 에 의해 추론되며 다음을 포함합니다.

  • root of trust 를 구성하는 자체 서명 (X.509) 인증서 목록
  • 이 공급자가 인증서 유효성 검사를 위해 고려하는 중간 CA를 나타내는 X.509 인증서 목록. 이러한 인증서는 신뢰의 루트에있는 인증서 중 하나만으로 인증 받아야합니다. 중간 CA는 선택적 매개 변수입니다.
  • 이 MSP의 관리자를 나타낼 수 있는 신뢰할 수있는 인증서 경로가있는 X.509 인증서 목록입니다. 이 인증서의 소유자는 이 MSP 구성 (예 : 루트 CA, 중간 CA)에 대한 변경을 요청할 수 있는 권한이 있습니다.
  • 이 MSP의 유효한 구성원이 X.509 인증서에 포함해야하는 조직 단위 목록 이것은 선택적 구성 매개 변수로, 예를 들어 여러 조직에서 동일한 신뢰 루트와 중간 CA를 활용하고 해당 구성원에 대해 OU 필드를 예약한 경우 사용됩니다
  • 나열된 (중간 또는 루트) MSP 인증 기관 중 정확히 하나에 각각 해당하는 인증서 해지 목록 (CRL) 목록 이것은 선택적 매개 변수입니다.
  • TLS 인증서 의 TLS root 를 구성하는 자체 서명 (X.509) 인증서 목록입니다 .
  • 이 공급자가 고려하는 중간 TLS CA를 나타내는 X.509 인증서 목록; 이 인증서는 TLS root of trust의 인증서 중 하나만으로 인증 받아야합니다. 중간 CA는 선택적 매개 변수입니다.

이 MSP 인스턴스의 유효한 ID는 다음 조건을 충족해야합니다.

  • 이들은 X.509 인증서의 형태로되어 있으며 신뢰할 수 있는 인증서 루트와 정확히 일치하는 하나의 인증서 경로가 있습니다.
  • CRL에는 포함되지 않습니다.
  • 또한 X.509 인증서 구조의 OU 필드에 MSP 구성의 조직 구성 단위 중 하나 이상을 나열합니다.

현재 MSP 구현에서 ID의 유효성에 대한 자세한 내용은 MSP Identity Validity Rules(MSP ID 유효성 규칙) 을 참조하십시오 .

검증 관련 매개 변수 외에도 MSP가 서명 또는 인증을 위해 인스턴스화 된 노드를 활성화하려면 다음을 지정해야합니다.

  • 노드에서 서명하는 데 사용되는 서명 키 (현재 ECDSA 키만 지원됨)
  • 노드의 X.509 인증서로,이 MSP의 확인 매개 변수 아래에 유효한 ID입니다.

MSP ID는 절대로 만료되지 않습니다. 해당 CRL에 추가하여 취소할 수 있습니다. 또한 현재 TLS 인증서 해지 시행을 지원하지 않습니다.

How to generate MSP certificates and their signing keys?

X.509 인증서를 생성하여 MSP 구성을 제공하려면 응용 프로그램에서 Openssl 을 사용할 수 있습니다. 우리는 Hyperledger Fabric에서 RSA 키를 포함한 인증서를 지원하지 않는다는 점을 강조합니다.

또는 cryptogen 도구를 사용할 수도 있습니다.이 도구의 작업 방법은 Getting Started(시작하기) 에서 설명 합니다.

Hyperledger Fabric CA 는 MSP를 구성하는 데 필요한 키와 인증서를 생성하는데도 사용할 수 있습니다.

MSP setup on the peer & orderer side

관리자는 로컬 MSP (Peer 또는 Orderer용)를 설정하려면 6 개의 하위 폴더와 파일을 포함 하는 폴더 (예 : $MY_PATH/mspconfig)를 만들어야 합니다.

  1. 관리자 인증서에 각각 해당하는 PEM 파일을 포함하는 admincerts 폴더
  2. 루트 CA의 인증서에 각각 해당하는 PEM 파일을 포함하는 cacerts 폴더
  3. (선택 사항) 중간 CA 인증서에 각각 해당하는 PEM 파일을 포함하는 intermediatecerts 폴더
  4. (선택 사항) 파일 config.yaml을 사용하여 지원되는 조직 단위 및 ID 분류를 구성합니다 (아래 각 절 참조).
  5. (선택 사항) 고려 대상 CRL을 포함할 crls 폴더
  6. 노드의 서명 키가 있는 PEM 파일을 포함 하는 keystore 폴더. 우리는 현재 RSA 키가 지원되지 않는다는 것을 강조한다.
  7. 노드의 X.509 인증서가 있는 PEM 파일을 포함하는 signcerts 폴더
  8. (선택 사항) TLS 루트 CA의 인증서에 각각 해당하는 PEM 파일을 포함하는 tlscacerts 폴더
  9. (선택 사항) 중간 TLS CA 인증서에 각각 해당하는 PEM 파일을 포함하는 tlsintermediatecerts 폴더

노드의 구성 파일 (Peer에 대한 core.yaml 파일 및 Orderer에 대한 orderer.yaml)에서 mspconfig 폴더의 경로와 노드의 MSP의 MSP 식별자를 지정해야합니다. mspconfig 폴더에 대한 경로는 FABRIC_CFG_PATH에 상대적인 것으로 예상되며 Peer에 대한 mspConfigPath 매개변수의 값으로 제공되고, Orderer는 LocalMSPDir로 제공됩니다. 노드의 MSP 식별자는 Peer에 대한 매개 변수 localMspId 및 Orderer에 대한 LocalMSPID 값으로 제공됩니다. 이러한 변수는 Peer에 대한 CORE 접두사 (예 : CORE_PEER_LOCALMSPID)와 Orderer의 ORDERER 접두사 (예 : ORDERER_GENERAL_LOCALMSPID)를 사용하여 환경을 통해 무시할 수 있습니다. 주문자 설정을 위해서는 시스템 채널의 genesis 블록을 생성하고 Orderer에게 제공해야합니다. 이 블록의 MSP 구성 요구 사항은 다음 절에서 자세히 설명합니다.

"로컬" MSP의 재구성 은 수동으로만 가능하며 Peer 또는 Orderer 프로세스가 다시 시작되어야합니다. 후속 릴리스에서는 온라인 / 동적 재구성 (노드 관리 시스템 체인 코드를 사용하여 노드를 중지 할 필요 없음)을 제공하는 것을 목표로합니다.

Organizational Units

이 MSP의 구성원이 유효한 X.509 인증서에 포함되어야하는 조직 구성 단위 목록을 구성하려면 config.yaml 파일에서 조직 구성 단위 식별자를 지정해야합니다. 다음은 그 예입니다 :

OrganizationalUnitIdentifiers:
  - Certificate: "cacerts/cacert1.pem"
    OrganizationalUnitIdentifier: "commercial"
  - Certificate: "cacerts/cacert2.pem"
    OrganizationalUnitIdentifier: "administrators"

위의 예에서는 두 개의 조직 구성 단위 식별자인 상업용(commercial) 및 관리자(administrators) 를 선언합니다. MSP ID는 이러한 조직 구성 단위 식별자 중 하나 이상을 포함하는 경우 유효합니다. 이 Certificate 필드는 특정 OU가있는 ID의 유효성을 검사해야하는 CA 또는 중간 CA 인증서 경로를 나타냅니다. 경로는 MSP 루트 폴더와 관련이 있으며 비워 둘 수 없습니다.

Identity Classification

기본 MSP 구현을 사용하면 x509 인증서의 OU를 기반으로 ID를 클라이언트 및 피어로 더 분류 할 수 있습니다. ID 는 트랜잭션을 제출하거나 피어를 쿼리하는 등의 경우 클라이언트(client) 로 분류되어야합니다. ID 는 트랜잭션을 승인하거나 커밋하는 경우 피어(peer) 로 분류되어야 합니다. 특정 MSP의 클라이언트 및 피어를 정의하려면 config.yaml 파일을 적절히 설정해야합니다. 다음은 그 예입니다.

NodeOUs:
  Enable: true
  ClientOUIdentifier:
    Certificate: "cacerts/cacert.pem"
    OrganizationalUnitIdentifier: "client"
  PeerOUIdentifier:
    Certificate: "cacerts/cacert.pem"
    OrganizationalUnitIdentifier: "peer" 

위에서 보여준 것처럼, NodeOUs.Enable 값은 true로 설정되어 신원 분류를 가능하게합니다. 그런 다음 client (peer) 식별자는 NodeOUs.ClientOUIdentifierNodeOUs.PeerOUIdentifier) 키에 대해 다음 속성을 설정하여 정의됩니다.

  1. OrganizationalUnitIdentifier : 클라이언트 (피어)의 x509 인증서에 포함해야하는 OU와 일치하는 값으로 설정합니다.
  2. Certificate : 이를 클라이언트 (피어) ID의 유효성을 검사해야하는 CA 또는 중간 CA로 설정합니다. 필드는 MSP 루트 폴더와 관련이 있습니다. 비어있을 수 있습니다. 즉, MSP 구성에 정의 된 모든 CA에서 ID의 x509 인증서를 확인할 수 있습니다.

분류가 활성화되면 MSP 관리자는 해당 MSP의 클라이언트여야합니다. 즉, x509 인증서는 클라이언트를 식별하는 OU를 전송해야합니다. 신원은 클라이언트 또는 피어가 될 수 있습니다. 두 분류는 상호 배타적입니다. ID가 클라이언트도 아니고 피어도 아닌 경우 유효성 검사가 실패합니다.

마지막으로, 업그레이드 된 환경에서는 분류 식별을 사용하기 전에 1.1 채널 기능을 활성화해야합니다.

Channel MSP setup

시스템의 초기 단계에서 네트워크에 나타나는 모든 MSP의 확인 매개 변수를 지정하고 시스템 채널의 genesis 블록에 포함해야합니다. MSP 확인 매개 변수는 MSP 식별자, 트러스트 인증서 루트, 중간 CA 및 관리자 인증서, OU 사양 및 CRL로 구성됩니다. 시스템 genesis 블록은 설치 단계에서 orderers에게 제공되며 채널 생성 요청을 인증할 수 있습니다. 명령자는 동일한 식별자를 가진 두 개의 MSP를 포함하는 경우 시스템 genesis 블록을 거부하므로 결과적으로 네트워크의 부트 스트랩이 실패합니다.

응용 프로그램 채널의 경우 채널을 관리하는 MSP의 확인 구성 요소만 채널의 genesis 블록에 있어야합니다. 우리는 하나 이상의 피어에게 채널에 참여하도록 지시하기 전에 올바른 MSP 구성 정보가 채널의 구성 블록 (또는 가장 최근 구성 블록)에 포함되도록하는 것이 응용 프로그램의 책임 임을 강조합니다 .

configtxgen 도구를 사용하여 채널을 부트 스트랩 할 때 mspconfig 폴더에 MSP의 확인 매개 변수를 포함하고 configtx.yaml의 해당 섹션에서 해당 경로를 설정하여 채널 MSP를 구성 할 수 있습니다.

해당 MSP의 CA와 관련된 인증서 해지 목록의 알림을 포함하여 채널에서 MSP를 다시 구성 하는 작업은 MSP의 관리자 인증서 중 하나의 소유자가 config_update 개체를 만들어서 수행합니다. 그러면 관리자가 관리하는 클라이언트 응용 프로그램은 이 MSP가 나타나는 채널에 이 업데이트를 알립니다.

Best Practices

이 섹션에서는 일반적으로 충족되는 시나리오에서 MSP 구성에 대한 모범 사례를 자세히 설명합니다.

1) 단체 / 기업과 MSP 간의 매핑

조직과 MSP 간에는 일대일 매핑이 권장됩니다. 다른 매핑 유형의 매핑이 선택되면 다음 사항을 고려해야합니다.

  • 다양한 MSP를 사용하는 한 조직. 이는 관리 독립성을 이유로 또는 개인 정보 보호를 이유로 MSP로 대표되는 다양한 부서를 포함하는 조직의 경우에 해당합니다. 이 경우 피어는 단일 MSP 만 소유할 수 있으며 다른 조직의 피어가 동일한 조직의 피어로 인식되지 않습니다. 이것이 의미하는 바는 동료는 가십 조직 범위의 데이터를 통해 동일한 조직의 구성원인 피어 집합과 공유할 수 있지만 실제 조직을 구성하는 전체 제공자 집합과 공유할 수는 없습니다.
  • 단일 MSP를 사용하는 여러 조직. 이것은 유사한 회원 구성에 의해 관리되는 조직의 컨소시엄의 경우에 해당합니다. 동일한 실제 조직에 속해 있는지 여부에 관계없이 동일한 MSP에서 신원을 가진 동료에게 동료 범위의 메시지를 전파해야한다는 것을 여기에서 알아야합니다. 이것은 MSP 정의 및 / 또는 피어 구성의 세분화 한계입니다.

2) 한 조직은 서로 다른 부서 (조직 단위)를 가지고 있으며 , 서로 다른 채널에 대한 액세스 권한을 부여하려고합니다.

이것을 처리하는 두 가지 방법 :

  • 모든 조직 구성원의 구성원 자격을 수용하도록 하나의 MSP를 정의하십시오. 해당 MSP의 구성은 루트 CA, 중간 CA 및 관리자 인증서 목록으로 구성됩니다. 회원 ID에는 회원이 소속된 조직 단위 (OU) 가 포함됩니다. 정책을 정의하여 특정 OU의 구성원을 파악할 수 있으며 이러한 정책은 채널의 읽기 / 쓰기 정책 또는 체인 코드의 승인 정책을 구성 할 수 있습니다. 이 접근 방식의 한계는 가십 피어가 로컬 MSP에서 회원 자격을 가진 동료를 동일한 조직의 구성원으로 간주하여 결과적으로 조직 범위의 데이터 (예 : 상태)를 가십을 수 있다는 것입니다.
  • 하나의 MSP를 정의하여 각 부서를 나타냅니다 . 여기에는 각 부서에 대해 루트 CA, 중간 CA 및 관리 인증서에 대한 인증서 집합이 지정되므로 MSP간에 중복되는 인증서 경로가 없어야합니다. 이는 예를 들어 세분당 다른 중간 CA가 사용됨을 의미합니다. 여기서 단점은 하나가 아닌 하나 이상의 MSP를 관리하는 것이지만 이전 방법에서 제기된 문제를 우회하는 것입니다. MSP 구성의 OU 확장을 활용하여 각 부서에 대해 하나의 MSP를 정의 할 수도 있습니다.

3) 고객을 동일한 조직의 동료와 분리합니다.

많은 경우에 신원의 "유형"을 신원 자체에서 검색할 수 있어야합니다 (예 : clients 또는 orderers로만 활동하는 노드가 아닌, peers가 보증을 보증해야하는 경우).

이러한 요구 사항에 대한 지원은 제한적입니다.

이러한 분리를 허용하는 한 가지 방법은 clients와 peers / orderers를 위한 하나의 노드 유형에 대해 별도의 중간 CA를 작성하는 것입니다. 두 개의 서로 다른 MSP를 구성하십시오. 하나는 clients용이고 다른 하나는 peers / orderers용입니다. 이 조직이 액세스해야하는 채널은 두 MSP를 모두 포함해야하며, 인증 정책은 동료를 참조하는 MSP만 사용합니다. 결국 궁극적으로 조직이 두 개의 MSP 인스턴스에 매핑되고 peers와 clients가 상호 작용하는 방식에 어떤 영향을 미칩니다.

동일한 조직의 모든 peers가 여전히 하나의 MSP에 속하기 때문에 가십(gossip)은 크게 영향을 받지 않습니다. peers는 특정 시스템 체인 코드의 실행을 로컬 MSP 기반 정책으로 제한할 수 있습니다. 예를 들어 peers는 clients인 로컬 MSP의 admin이 요청을 서명한 경우 (최종 사용자가 요청의 출처에 있어야 함) "joinChannel" 요청만 실행합니다. peer / orderer MSP의 멤버가되는 유일한 클라이언트가 해당 MSP의 관리자가 된다는 사실을 받아들이면 이 불일치를 해결할 수 있습니다.

이 접근법과 함께 고려해야 할 또 다른 포인트는 피어가 자신의 로컬 MSP 내의 요청 발신자의 회원 자격을 기반으로 이벤트 등록 요청을 승인하는 것입니다. 분명히, 요청의 발신자가 클라이언트이기 때문에, 요청 발신자는 요청된 피어와 다른 MSP에 속하도록 항상 운명 지워지고 피어는 요청을 거부합니다.

4) 관리자 및 CA 인증서

root of trust 또는 중간 CA에 대해 MSP에서 고려한 인증서와 다른 MSP 관리 인증서로 설정하는 것이 중요합니다. 이는 구성원 구성 요소 관리의 의무를 새 인증서 발급 및 / 또는 기존 인증서 유효성 검사와 구분하는 일반적인 (보안) 방법입니다.

5) 중간 CA를 블랙리스트에 올린다.

이전 섹션에서 언급했듯이 MSP의 재구성은 재구성 메커니즘 (로컬 MSP 인스턴스의 수동 재구성 및 채널의 MSP 인스턴스에 대해 올바르게 구성된 config_update 메시지를 통해 수행)을 통해 이루어집니다. 분명히, MSP에서 고려되는 중간 CA가 더 이상 해당 MSP의 신원 확인을 위해 고려되지 않는지 확인하는 두 가지 방법이 있습니다.

  1. 신뢰할 수 있는 중간 CA 인증서 목록에 해당 중간 CA 인증서를 더 이상 포함하지 않도록 MSP를 다시 구성합니다. 로컬로 구성된 MSP의 경우 이 CA의 인증서가 해당 intermediatecerts 폴더에서 제거되었음을 의미합니다.
  2. 언급된 중간 CA의 인증서를 거부하는 root of trust에서 생성된 CRL을 포함하도록 MSP를 다시 구성합니다.

현재 MSP 구현에서 우리는 더 간단하고 더 이상 고려되지 않는 중간 CA를 블랙리스트에 올 필요가 없으므로 방법 (1) 만 지원합니다.

6) CA와 TLS CA

MSP ID의 루트 CA와 MSP TLS 인증서의 루트 CA (및 상대 중간 CA)는 서로 다른 폴더에 선언해야합니다. 이는 서로 다른 클래스의 인증서 간에 혼란을 피하기 위한 것입니다. MSP ID와 TLS 인증서 모두에 대해 동일한 CA를 재사용하는 것이 금지되어 있지는 않지만 최선의 방법은 프로덕션 환경에서 이를 피하기 위한 것입니다.

Channel Configuration (configtx)

Channel Configuration (configtx)

Hyperledger 패브릭 블록 체인 네트워크의 공유 구성은 채널 당 하나의 컬렉션 구성 트랜잭션에 저장됩니다. 각 구성 트랜잭션은 일반적으로 더 짧은 이름 configtx로 참조 됩니다.

채널 구성에는 다음과 같은 중요한 속성이 있습니다.

  1. Versioned : 구성의 모든 요소에는 모든 수정 작업을 수행 할 수 있는 관련 버전이 있습니다. 또한 커밋된 모든 구성은 시퀀스 번호를 받습니다.
  2. Permissioned : 구성의 각 요소에는 해당 요소에 대한 수정이 허용되는지 여부를 결정하는 관련 정책이 있습니다. 이전 configtx 사본이 있고 추가 정보가 없는 사용자는 이 정책을 기반으로 새 구성의 유효성을 확인할 수 있습니다.
  3. Hierarchical : 루트 구성 그룹에는 하위 그룹이 포함되며 계층 구조의 각 그룹에는 연관된 값과 정책이 있습니다. 이러한 정책은 계층을 활용하여 하위 수준의 정책에서 한 수준의 정책을 유도합니다.

Anatomy of a configuration

구성은 다른 트랜잭션이 없는 블록에 HeaderType_CONFIG 유형의 트랜잭션으로 저장됩니다. 이러한 블록을 구성 블록(Configuration Blocks) 이라고하며 , 그 중 첫 번째 블록을 기원 블록(Genesis Block) 이라고 합니다.

구성을 위한 프로토 구조는 fabric/protos/common/configtx.proto에 저장됩니다. HeaderType_CONFIG 유형의 언벨로프(Envelope)는 Payload data 필드로 ConfigEnvelope 메시지를 인코딩합니다. ConfigEnvelope의 프로토 타입은 다음과 같이 정의됩니다 :

message ConfigEnvelope {
    Config config = 1;
    Envelope last_update = 2;
}

이 last_update 필드는 아래의 구성 업데이트 섹션에서 정의되지만 구성을 검증할 때만 필요합니다. 대신 현재 커밋된 구성은 Config 메시지를 포함하는 config 필드에 저장됩니다.

message Config {
    uint64 sequence = 1;
    ConfigGroup channel_group = 2;
}

sequence 번호는 커밋된 구성마다 하나씩 증가합니다. channel_group 필드는 구성을 포함하는 루트 그룹입니다. ConfigGroup 구조는 재귀 정의되며, 각 그룹에는 값과 정책을 포함하는 각각의 그룹의 트리를 구축합니다. 그것은 다음과 같이 정의됩니다 :

message ConfigGroup {
    uint64 version = 1;
    map<string,ConfigGroup> groups = 2;
    map<string,ConfigValue> values = 3;
    map<string,ConfigPolicy> policies = 4;
    string mod_policy = 5;
}

ConfigGroup은 재귀적 구조이므로 계층적인 배열을가집니다. 다음 예는 golang 표기법을 명확하게 표현한 것입니다 :

// Assume the following groups are defined
var root, child1, child2, grandChild1, grandChild2, grandChild3 *ConfigGroup

// Set the following values
root.Groups["child1"] = child1
root.Groups["child2"] = child2
child1.Groups["grandChild1"] = grandChild1
child2.Groups["grandChild2"] = grandChild2
child2.Groups["grandChild3"] = grandChild3

// The resulting config structure of groups looks like:
// root:
//     child1:
//         grandChild1
//     child2:
//         grandChild2
//         grandChild3

각 그룹은 구성 계층에서 수준을 정의하며 각 그룹은 관련된 값 집합 (문자열 키로 인덱싱 됨)과 정책 (문자열 키로 인덱싱 됨)을 갖습니다.

값은 다음과 같이 정의됩니다 :

message ConfigValue {
    uint64 version = 1;
    bytes value = 2;
    string mod_policy = 3;
}

정책은 다음과 같이 정의됩니다 :

message ConfigPolicy {
    uint64 version = 1;
    Policy policy = 2;
    string mod_policy = 3;
}

값, 정책 및 그룹에는 모두 version과 mod_policy가 있습니다. 요소의 version은 해당 엘리먼트가 수정 될 때마다 증가됩니다. mod_policy는 해당 요소를 수정하는 데 필요한 서명을 적용하는 데 사용됩니다. 그룹의 경우 수정은 값, 정책 또는 그룹 맵에 요소를 추가하거나 제거하는 것입니다 (또는 mod_policy 변경). 값 및 정책의 경우 수정은 값 및 정책 필드를 각각 변경합니다 (또는 mod_policy 변경). 각 요소의 mod_policy는 현재 구성 수준의 컨텍스트에서 평가됩니다. Channel.Groups["Application"]에 정의된 다음 mod 정책 예제를 고려하십시오 (여기서 golang 맵 참조 구문을 사용하므로Channel.Groups["Application"].Policies["policy1"]은 기본 Channel 그룹의 Application 그룹의 Policies 맵 policy1 정책을 참조하십시오).

  • policy1은 Channel.Groups["Application"].Policies["policy1"]에 매핑됩니다.
  • Org1/policy2Channel.Groups["Application"].Groups["Org1"].Policies["policy2"]에 매핑됩니다.
  • /Channel/policy3은 Channel.Policies["policy3"]에 매핑됩니다.

mod_policy가 존재하지 않는 정책을 참조하는 경우 해당 항목을 수정할 수 없습니다.

Configuration updates

구성 업데이트는 HeaderType_CONFIG_UPDATE 유형의 Envelope 메시지로 제출됩니다. 트랜잭션의 Payload data는 marshaled된 ConfigUpdateEnvelope입니다. ConfigUpdateEnvelope는 다음과 같이 정의됩니다.

message ConfigUpdateEnvelope {
    bytes config_update = 1;
    repeated ConfigSignature signatures = 2;
}

이 signatures 필드에는 구성 업데이트를 인증하는 일련의 서명이 들어 있습니다. 메시지 정의는 다음과 같습니다 :

message ConfigSignature {
    bytes signature_header = 1;
    bytes signature = 2;
}

signature_header는 표준 트랜잭션에 정의된 대로 서명은 signature_header 바이트와 ConfigUpdateEnvelope 메시지의 config_update 바이트의 연결을 넘습니다.

ConfigUpdateEnvelope config_update 바이트는 다음과 같이 정의된 marshaled된 ConfigUpdate 메시지입니다 :

message ConfigUpdate {
    string channel_id = 1;
    ConfigGroup read_set = 2;
    ConfigGroup write_set = 3;
}

channel_id는 업데이트가 바인딩된 채널 ID이며, 이 재구성을 지원하는 서명의 범위를 지정하는 데 필요합니다.

read_set은 version 필드만 설정되고 다른 필드는 채워져서는 안되는 것으로 지정된 기존 구성의 하위 집합을 지정합니다. 특정 ConfigValue value 또는 ConfigPolicy policy 필드는 read_set에 절대로 설정해서는 안됩니다. ConfigGroup은 config 트리의 더 깊은 요소를 참조할 수 있도록, 맵 필드의 하위 집합을 채울 수 있습니다. 예를 들어, Application 그룹을 read_set에 포함시키려면 그 부모 (Channel 그룹)도 읽기 세트에 포함되어야하지만 Channel 그룹은 모든 키를 채울 필요가 없습니다. Orderer group 키 또는 아무 valuespolicies 키 중 하나를 선택하십시오.

write_set는 수정된 구성을 지정합니다. 구성의 계층적 특성으로 인해 계층 구조의 깊숙한 요소에 대한 쓰기는 해당 write_set 계층의 상위 수준 요소를 포함해야합니다. 그러나, 동일한 버전의 read_set에도 지정된 write_set의 요소는 read_set에서와 같이 드문드문하게 지정해야 합니다.

예를 들어, 구성이 주어진 경우 :

Channel: (version 0)
    Orderer (version 0)
    Appplication (version 3)
       Org1 (version 2)

Org1을 수정하는 구성 업데이트를 제출하려면 read_set이 다음과 같습니다 :

Channel: (version 0)
    Application: (version 3)

write_set은 다음과 같습니다.

Channel: (version 0)
    Application: (version 3)
        Org1 (version 3)

CONFIG_UPDATE가 수신되면 orderer는 다음을 수행하여 결과 CONFIG를 계산합니다.

  1. channel_id및 read_set을 확인합니다. read_set의 모든 요소는 지정된 버전에 존재해야합니다.
  2. read_set에 동일한 버전으로 나타나지 않는 write_set의 모든 요소를 ​​수집하여 업데이트 세트(update set)를 계산합니다 .
  3. 업데이트 세트의 각 요소가 요소 업데이트의 버전 번호를 정확히 1만큼 증가시키는 지 확인합니다.
  4. ConfigUpdateEnvelope에 첨부된 서명 세트가 업데이트 세트의 각 요소에 대해 mod_policy를 충족하는지 확인합니다.
  5. 업데이트 세트를 현재 구성에 적용하여 새로운 전체 버전의 구성을 계산합니다.
  6. 새 구성을 ConfigEnvelope에 기록하고 CONFIG_UPDATE를 last_update 필드로, config 필드에 인코딩된 새 구성을 증가된 sequence 값과 함께 기록합니다.
  7. 새 ConfigEnvelope를 CONFIG 유형의 Envelope에 기록하고 궁극적으로 이것을 새로운 구성 블록에 단독 트랜잭션으로 씁니다.

피어 (또는 다른 Deliver 수신자)가 이 구성 블록을 수신하면 현재 구성에 last_update 메시지를 적용하고 순서대로 계산된 config 필드에 올바른 새로운 구성이 들어 있는지 확인하여 구성이 적절하게 유효성이 검증되었는지 확인해야합니다 .

Permitted configuration groups and values

유효한 구성은 다음 구성의 서브 세트입니다. 여기서 우리는 peer.<MSG> 표기법을 사용하여 value 필드가 fabric/protos/peer/configuration.proto에 정의된 <MSG> 이름의 marshaled된 프로토 메시지임을 나타내는 ConfigValue를 정의합니다. common.<MSG>msp.<MSG> 및 orderer.<MSG>의 표기법은 비슷하지만, fabric/protos/common/configuration.proto, fabric/protos/msp/mspconfig.protofabric/protos/orderer/configuration.proto에서 정의된 메시지를 사용합니다.

키 {{org_name}}과 {{consortium_name}}은 임의의 이름을 나타내며 다른 이름으로 반복될 수 있는 요소를 나타냅니다.

&ConfigGroup{
    Groups: map<string, *ConfigGroup> {
        "Application":&ConfigGroup{
            Groups:map<String, *ConfigGroup> {
                {{org_name}}:&ConfigGroup{
                    Values:map<string, *ConfigValue>{
                        "MSP":msp.MSPConfig,
                        "AnchorPeers":peer.AnchorPeers,
                    },
                },
            },
        },
        "Orderer":&ConfigGroup{
            Groups:map<String, *ConfigGroup> {
                {{org_name}}:&ConfigGroup{
                    Values:map<string, *ConfigValue>{
                        "MSP":msp.MSPConfig,
                    },
                },
            },

            Values:map<string, *ConfigValue> {
                "ConsensusType":orderer.ConsensusType,
                "BatchSize":orderer.BatchSize,
                "BatchTimeout":orderer.BatchTimeout,
                "KafkaBrokers":orderer.KafkaBrokers,
            },
        },
        "Consortiums":&ConfigGroup{
            Groups:map<String, *ConfigGroup> {
                {{consortium_name}}:&ConfigGroup{
                    Groups:map<string, *ConfigGroup> {
                        {{org_name}}:&ConfigGroup{
                            Values:map<string, *ConfigValue>{
                                "MSP":msp.MSPConfig,
                            },
                        },
                    },
                    Values:map<string, *ConfigValue> {
                        "ChannelCreationPolicy":common.Policy,
                    }
                },
            },
        },
    },

    Values: map<string, *ConfigValue> {
        "HashingAlgorithm":common.HashingAlgorithm,
        "BlockHashingDataStructure":common.BlockDataHashingStructure,
        "Consortium":common.Consortium,
        "OrdererAddresses":common.OrdererAddresses,
    },
}

Orderer system channel configuration

Ordering 시스템 채널은 Ordering 매개 변수와 채널 생성을 위한 컨소시엄을 정의해야 합니다. Ordering 서비스를 위해서는 정확히 하나의 Ordering 시스템 채널이 있어야하며, 생성된 (또는 더 정확하게 부트스트랩 된) 첫 번째 채널입니다. Ordering 시스템 채널 기원(genesis) 구성 내에서 응용 프로그램 섹션을 정의하지 않는 것이 좋습니다. 그러나 테스트를 위해 수행할 수 있습니다. Ordering 시스템 채널에 대한 읽기 권한을 가진 회원은 모든 채널 생성을 볼 수 있으므로 이 채널의 액세스가 제한되어야합니다.

Ordering 매개 변수는 config의 다음 서브 세트로 정의됩니다.

&ConfigGroup{
    Groups: map<string, *ConfigGroup> {
        "Orderer":&ConfigGroup{
            Groups:map<String, *ConfigGroup> {
                {{org_name}}:&ConfigGroup{
                    Values:map<string, *ConfigValue>{
                        "MSP":msp.MSPConfig,
                    },
                },
            },

            Values:map<string, *ConfigValue> {
                "ConsensusType":orderer.ConsensusType,
                "BatchSize":orderer.BatchSize,
                "BatchTimeout":orderer.BatchTimeout,
                "KafkaBrokers":orderer.KafkaBrokers,
            },
        },
    },

ordering에 참여하는 각 조직에는 Orderer 그룹 아래에 그룹 요소가있습니다. 이 그룹은 해당 조직에 대한 암호화 신원 정보를 포함하는 단일 매개 변수 MSP를 정의합니다. Orderer 그룹의 Values에 따라 주문 노드가 작동하는 방식이 결정됩니다. 채널마다 존재하므로 orderer.BatchTimeout은 한 채널에서 다른 채널과 다르게 지정될 수 있습니다.

시작시, orderer는 많은 채널에 대한 정보가 들어있는 파일 시스템에 직면하게됩니다. orderer는 컨소시엄 그룹이 정의된 채널을 식별하여 시스템 채널을 식별합니다. 컨소시엄 그룹의 구조는 다음과 같습니다.

&ConfigGroup{
    Groups: map<string, *ConfigGroup> {
        "Consortiums":&ConfigGroup{
            Groups:map<String, *ConfigGroup> {
                {{consortium_name}}:&ConfigGroup{
                    Groups:map<string, *ConfigGroup> {
                        {{org_name}}:&ConfigGroup{
                            Values:map<string, *ConfigValue>{
                                "MSP":msp.MSPConfig,
                            },
                        },
                    },
                    Values:map<string, *ConfigValue> {
                        "ChannelCreationPolicy":common.Policy,
                    }
                },
            },
        },
    },
},

각 컨소시엄은 ordering 조직의 조직 구성원과 마찬가지로 구성원 집합을 정의합니다. 각 컨소시엄은 ChannelCreationPolicy 또한 정의합니다. 이 정책은 채널 생성 요청을 승인하는 데 적용됩니다. 일반적으로 이 값은 채널의 새 구성원이 채널 생성을 승인하도록 요구하는 ImplicitMetaPolicy로 설정됩니다. 채널 생성에 대한 자세한 내용은이 문서 뒷부분에 나와 있습니다.

Application channel configuration

애플리케이션 구성은 애플리케이션 유형 트랜잭션을 위해 설계된 채널을 위한 것입니다. 그것은 다음과 같이 정의됩니다 :

&ConfigGroup{
    Groups: map<string, *ConfigGroup> {
        "Application":&ConfigGroup{
            Groups:map<String, *ConfigGroup> {
                {{org_name}}:&ConfigGroup{
                    Values:map<string, *ConfigValue>{
                        "MSP":msp.MSPConfig,
                        "AnchorPeers":peer.AnchorPeers,
                    },
                },
            },
        },
    },
}

Orderer 섹션과 마찬가지로 각 조직은 그룹으로 인코딩됩니다. 그러나 MSP 신원 정보만 인코딩하는 대신 각 조직은 AnchorPeers의 목록을 추가로 인코딩합니다. 이 목록은 다른 조직의 피어가 피어 가십 네트워킹(peer gossip networking)을 위해 서로 접촉할 수 있게 합니다.

응용 프로그램 채널은 이 매개 변수의 결정적 업데이트를 허용하기 위해 oderer org 및 합의(consensus) 옵션의 사본을 인코딩하므로 orderer 시스템 채널 구성의 동일한 Orderer 섹션이 포함됩니다. 그러나 응용 프로그램 관점에서 이것은 크게 무시 될 수 있습니다.

Channel creation

orderer가 존재하지 않는 채널에 대해 CONFIG_UPDATE를 수신하면, orderer는 이것이 채널 작성 요청이어야한다고 가정하고 다음을 수행합니다.

  1. orderer는 채널 생성 요청이 수행될 컨소시엄을 식별합니다. 최상위 레벨 그룹의 Consortium 값을 보고 이를 수행합니다 .
  2. orderer는 Application그룹에 포함된 조직이 해당 컨소시엄에 포함된 조직의 하위 집합이며 ApplicationGroup이 version 1로 설정되어 있는지 확인합니다.
  3. orderer는 컨소시엄에 회원이 있는 경우 새 채널에도 애플리케이션 회원 (생성 컨소시엄 및 멤버가 없는 채널은 테스트에만 유용함)이 있는지 확인합니다.
  4. orderer는 ordering 시스템에서 Orderer 그룹을 가져와서 새로 지정된 멤버로 Application 그룹을 만들고 해당 mod_policy를 컨소시엄 구성에 지정된대로 ChannelCreationPolicy로 지정하여 템플릿 구성을 만듭니다. 정책은 새로운 구성 컨텍스트에서 평가되므로 ALL 구성원을 요구하는 정책에는 컨소시엄의 모든 구성원이 아닌 모든 새 채널 구성원의 서명이 필요합니다.
  5. 그러면 orderer는 CONFIG_UPDATE를 이 템플릿 구성에 대한 갱신 사항으로 적용합니다. CONFIG_UPDATEApplication 그룹 (해당 version은 1)에 수정 사항을 적용하기 때문에 구성 코드는 ChannelCreationPolicy에 대해 이러한 업데이트의 유효성을검사합니다. 채널 생성에 개별 조직의 앵커 피어 (peer peer)와 같은 다른 수정 사항이 포함되어있는 경우 요소에 해당하는 mod 정책이 호출됩니다.
  6. 새 채널 구성을 사용하는 새로운 CONFIG 트랜잭션은 ordering 시스템 채널에서 ordering을 위해 포장되어 전송됩니다. ordering 후에 채널이 생성됩니다.

Endorsement policies

보증 정책 내용

https://stackoverflow.com/questions/48108709/what-are-members-and-admins-in-endorsement-policy-of-hyperledger-fabric

Endorsement policies

보증 정책은 거래가 적절하게 보증되는지 여부를 결정하는 방법을 피어에게 지시하는 데 사용됩니다. 피어가 트랜잭션을 수신하면 트랜잭션 유효성 검증 플로우의 일부로 트랜잭션의 체인 코드와 연관된 VSCC (유효성 검증 시스템 체인 코드)를 호출하여 트랜잭션의 유효성을 판별합니다. 보증(endorsing)이 많은 피어로부터 하나 이상의 보증(endorsement)을 포함한다는 것을 상기하십시오. VSCC는 다음 결정을 내려야합니다 :

  • 모든 보증은 유효합니다 (즉, 예상 메시지에 대한 유효한 인증서의 유효한 서명입니다)
  • 적절한 수의 보증이 있다.
  • 보증은 예상된 소스에서 나온 것입니다.

보증 정책은 두 번째 및 세 번째 점을 지정하는 방법입니다.

Endorsement policy syntax in the CLI

CLI에서는 간단한 언어를 사용하여 원칙에 대한 부울 표현에 대한 정책을 표현합니다.

principal은 서명자의 신원을 확인하고 서명자가 해당 MSP 내에서 갖는 역할을 확인하는 임무를 맡은 MSP의 관점에서 설명합니다. 구성원(member) , 관리자(admin) , 클라이언트(client) 및 피어(peer)의 네 가지 역할이 지원됩니다 . principal은 MSPROLE로 설명됩니다. 여기서 MSP는 필수 MSP의 ID이며, ROLEmemberadminclient및 peer의 네 개의 문자열 중 하나입니다. 유효한 주체의 예로는 'Org0.admin'Org0 MSP의 모든 관리자 ) 또는 'Org1.member'Org1 MSP의 모든 구성원), 'Org1.client'Org1 MSP 클라이언트 ) 및 'Org1.peer'Org1 MSP의 피어 )입니다.

언어 구문은 다음과 같습니다. :

EXPR(E[, E...])

여기에서 EXPR은 두 개의 부울 표현식을 나타내는 AND 또는 OR이고 E는 principal(위에 설명 된 구문을 사용하는) 이거나 EXPR에 대한 다른 중첩 호출입니다.

예 :
  • AND('Org1.member', 'Org2.member', 'Org3.member')는 3 명의 주체(principal) 각자에게서 1 개의 서명을 요구한다.
  • OR('Org1.member', 'Org2.member')은 두 명의 주체(principal) 중 한 명에게 1 개의 서명을 요구한다.
  • OR('Org1.member', AND('Org2.member', 'Org3.member'))Org1 MSP의 멤버로부터 하나의 서명 또는, Org2 MSP의 멤버로부터 하나의 서명을, 그리고 Org3 MSP의 멤버로부터 하나의 서명을 요청합니다.

Specifying endorsement policies for a chaincode

체인 코드 배포자는 이 언어를 사용하여 지정된 정책에 대해 체인 코드의 인증을 확인하도록 요청할 수 있습니다.

Note! 인스턴스 생성시 지정되지 않은 경우 보증 정책은 기본적으로 "채널에 있는 조직의 모든(any) 구성원"으로 지정됩니다. 예를 들어 'Org1' 및 'Org2'가 포함된 채널의 기본 보증 정책은 'OR ('Org1.member ','Org2.member ')입니다.

-P 스위치를 사용하여 인스턴스를 생성 할 때 정책을 지정할 수 있으며 그 뒤에 정책이 옵니다.

 :

peer chaincode instantiate -C <channelid> -n mycc -P "AND('Org1.member', 'Org2.member')"

이 명령은 Org1 및 Org2 구성원이 트랜잭션에 서명해야하는 AND('Org1.member', 'Org2.member') 정책으로 chaincode mycc를 배포 합니다.

ID 분류가 활성화된 경우(Membership Service Providers (MSP) 참조) PEER 역할을 사용하여 peers에게만 보증을 제한할 수 있습니다.

 :

peer chaincode instantiate -C <channelid> -n mycc -P "AND('Org1.peer', 'Org2.peer')"

Note! 인스턴스 생성 후 채널에 추가된 새 조직은 체인 코드를 쿼리할 수 ​​있지만 (쿼리에 채널 정책 및 체인 코드에 의해 적용되는 모든 응용 프로그램 수준 검사가 정의한 적절한 권한을 가지고 있음에도 불구하고 체인 코드로 승인된 트랜잭션을 커밋 할 수는 없습니다). 새로운 조직의 보증을 통해 트랜잭션을 커밋 할 수 있도록 보증 정책을 수정해야합니다(Upgrade and Invoke Chaincode 참조).

Error handling

 Error handling

General Overview

Hyperledger 패브릭 코드는 Go에서 제공하는 표준 오류 유형 대신 판매된 패키지 github.com/pkg/errors 를 사용해야합니다. 이 패키지는 오류 메시지가 있는 스택 추적을 쉽게 생성하고 표시 할 수 있습니다.

Usage Instructions

fmt.Errorf() 또는 errors.New()에 대한 모든 호출 대신 github.com/pkg/errors를 사용해야합니다. 이 패키지를 사용하면 오류 메시지에 추가될 호출 스택이 생성됩니다.

이 패키지를 사용하는 것은 간단하며 코드를 쉽게 조정할 수 있습니다.

먼저 github.com/pkg/errors를 가져와야 합니다.

그런 다음 오류 생성 함수 (errors.New (), errors.Errorf (), errors.WithMessage (), errors.Wrap (), errors.Wrapf () 중 하나를 사용하도록 코드에서 생성된 모든 오류를 업데이트하십시오.

Note! 사용 가능한 오류 생성 기능에 대한 자세한 내용은 https://godoc.org/github.com/pkg/errors를 참조 하십시오. 또한 패브릭 코드에 패키지를 사용하기 위한 구체적인 지침은 아래의 일반 지침 섹션을 참조하십시오.

마지막으로, 로거 또는 fmt.Printf() 호출에 대한 형식 지시자를 %s에서 %+v로 변경하여 호출 스택을 오류 메시지와 함께 출력하십시오.

General guidelines for error handling in Hyperledger Fabric

  • 사용자 요청을 처리하는 중이라면 오류를 기록한 다음 반환해야합니다.
  • Go 라이브러리 나 판매자 패키지와 같은 외부 소스에서 오류가 발생하면 errors.Wrap()을 사용하여 오류를 래핑하여 오류에 대한 호출 스택을 생성하십시오.
  • 다른 패브릭 함수에서 오류가 발생하면 호출 스택을 영향을받지 않고 errors.WithMessage()를 사용하여 오류 메시지에 추가 컨텍스트를 추가하십시오.
  • 패닉이 다른 패키지로 퍼지면 안됩니다.

Example program

다음 예제 프로그램은 패키지 사용에 대한 명확한 데모를 제공합니다.

package main

import (
  "fmt"

  "github.com/pkg/errors"
)

func wrapWithStack() error {
  err := createError()
  // do this when error comes from external source (go lib or vendor)
  return errors.Wrap(err, "wrapping an error with stack")
}
func wrapWithoutStack() error {
  err := createError()
  // do this when error comes from internal Fabric since it already has stack trace
  return errors.WithMessage(err, "wrapping an error without stack")
}
func createError() error {
  return errors.New("original error")
}

func main() {
  err := createError()
  fmt.Printf("print error without stack: %s\n\n", err)
  fmt.Printf("print error with stack: %+v\n\n", err)
  err = wrapWithoutStack()
  fmt.Printf("%+v\n\n", err)
  err = wrapWithStack()
  fmt.Printf("%+v\n\n", err)
}

Logging Control

Logging Control

Overview

peer 응용 프로그램 및 shim 인터페이스에서 체인 코드 로깅은 github.com/op/go-logging 패키지에서 제공하는 기능을 사용하여 프로그래밍 됩니다. 이 패키지는

  • 메시지의 심각도를 기반으로 로깅 제어
  • 메시지를 생성하는 소프트웨어 모듈을 기반으로 한 로깅 제어
  • 메시지의 심각도를 기반으로 한 다양한 pretty-printing 옵션

모든 로그는 현재 stderr로 이동되며 pretty-printing은 현재 수정되었습니다. 그러나 심각도 별 로깅의 전역 및 모듈 수준 제어는 사용자와 개발자 모두에게 제공됩니다. 현재 각 심각도 수준에서 제공되는 정보 유형에 대한 형식화 된 규칙은 없지만 버그 보고서를 제출할 때 개발자는 전체 로그를 DEBUG 수준으로 보고 싶어 할 수 있습니다.

pretty-printing 로그에서 로깅 수준은 색상과 4 자리 코드로 표시됩니다 (예 : ERROR에 ERRO, DEBU에 DEBUG 등). 로깅 컨텍스트에서 모듈 은 임의의 이름 (문자열)입니다. 개발자가 관련 메시지 그룹에 제공합니다. 아래의 예에서, "peer", "rest"및 "main"로깅 모듈은 로그를 생성합니다.

16:47:09.634 [peer] GetLocalAddress -> INFO 033 Auto detected peer address: 9.3.158.178:7051
16:47:09.635 [rest] StartOpenchainRESTServer -> INFO 035 Initializing the REST service...
16:47:09.635 [main] serve -> INFO 036 Starting peer with id=name:"vp1" , network id=dev, address=9.3.158.178:7051, discovery.rootnode=, validator=true

런타임에 임의의 수의 로깅 모듈을 생성할 수 있으므로 모듈의 "마스터 목록"이 없고 로깅 제어 구조가 로깅 모듈이 실제로 존재하는지 또는 존재하는지 여부를 확인할 수 없습니다. 또한 로깅 모듈 시스템은 계층 구조 또는 와일드 카드를 이해하지 못합니다. 코드에서 "foo/bar"와 같은 모듈 이름을 볼 수 있지만 로깅 시스템은 플랫 문자열만 볼 수 있습니다. "foo/bar"는 어떤 식 으로든 "foo"와 관련이 있거나 "foo/*"가 foo의 모든 "하위 모듈"을 나타낼 수 있다는 것을 이해하지 못합니다.

peer

peer 명령의 로깅 수준은 --logging-level 플래그를 사용하여 각 호출에 대해 명령 줄에서 제어 할 수 있습니다 ( 예 :

peer node start --logging-level=debug

각 개별 peer 하위 명령의 기본 로깅 레벨은 core.yaml 파일에서 설정할 수도 있습니다. 예를 들어, 키 logging.node는 node 서브 커맨드의 기본 레벨을 설정합니다. 이 파일의 주석은 환경 변수를 사용하여 다양한 방법으로 로깅 수준을 재정의하는 방법을 설명합니다.

로깅 심각도 수준은 다음에서 선택된 대/소문자를 구분하지 않는 문자열을 사용하여 지정됩니다.

CRITICAL | ERROR | WARNING | NOTICE | INFO | DEBUG

peer의 전체 로깅 수준 사양은 다음과 같습니다.

[<module>[,<module>...]=]<level>[:[<module>[,<module>...]=]<level>...]

로깅 레벨 자체가 전체 기본값으로 간주됩니다. 그렇지 않으면 모듈의 개별 또는 그룹에 대한 재정의는 다음을 사용하여 지정할 수 있습니다.

<module>[,<module>...]=<level>

구문. 사양 예 ( --logging-level, 환경 변수 및 core.yaml 설정 모두에 유효 ) :

info                                       - Set default to INFO
warning:main,db=debug:chaincode=info       - Default WARNING; Override for main,db,chaincode
chaincode=info:main=debug:db=debug:warning - Same as above

Go chaincodes

체인 코드 애플리케이션 내에서 로그하는 표준 메커니즘은 피어를 통해 각 체인 코드 인스턴스에 노출된 로깅 전송과 통합하는 것입니다. chaincode shim 패키지는 체인 코드가 로그를 형식화하고 shim 로그와 일관되게 인터리브되는 로깅 객체를 생성하고 관리할 수 있게 해주는 API를 제공합니다.

독자적으로 실행되는 프로그램처럼, 사용자 제공 체인 코드는 기술적으로 stdout/stderr에 출력을 생성할 수도 있습니다. 자연적으로 "devmode"에 유용하지만 일반적으로 프로덕션 네트워크에서는 이러한 채널이 손상되어 악성 코드의 악용을 방지합니다. 그러나 CORE_VM_DOCKER_ATTACHSTDOUT = true 구성 옵션을 통해 피어가 관리하는 컨테이너 (예 : "netmode")의 경우에도 이 출력을 피어 단위로 활성화 할 수 있습니다.

일단 활성화되면, 각 체인 코드는 해당 컨테이너 ID에 의해 자체 로깅 채널을 수신하게됩니다. stdout 또는 stderr에 기록된 출력은 각 행별로 피어의 로그와 통합됩니다. 프로덕션 환경에서 이를 활성화하는 것은 권장되지 않습니다.

API

NewLogger(name string) *ChaincodeLogger - 체인 코드에서 사용할 로깅 개체 만들기 (c *ChaincodeLogger) SetLevel(level LoggingLevel) - 로거의 로깅 수준 설정

(c *ChaincodeLogger) IsEnabledFor(level LoggingLevel) bool - 지정된 레벨에서 로그가 생성되면 true를 반환합니다.

LogLevel(levelString string) (LoggingLevel, error) - 문자열을 LoggingLevel로 변환하십시오.

LoggingLevel은 열거 형의 멤버입니다.

LogDebug, LogInfo, LogNotice, LogWarning, LogError, LogCritical

대/소문자를 구별하지 않는 버전의 문자열을 전달하여 직접 사용할 수 있습니다.

DEBUG, INFO, NOTICE, WARNING, ERROR, CRITICAL

LogLevel API.

다양한 심각도 수준의 형식화 된 로깅은 함수에 의해 제공됩니다.

(c *ChaincodeLogger) Debug(args ...interface{})
(c *ChaincodeLogger) Info(args ...interface{})
(c *ChaincodeLogger) Notice(args ...interface{})
(c *ChaincodeLogger) Warning(args ...interface{})
(c *ChaincodeLogger) Error(args ...interface{})
(c *ChaincodeLogger) Critical(args ...interface{})

(c *ChaincodeLogger) Debugf(format string, args ...interface{})
(c *ChaincodeLogger) Infof(format string, args ...interface{})
(c *ChaincodeLogger) Noticef(format string, args ...interface{})
(c *ChaincodeLogger) Warningf(format string, args ...interface{})
(c *ChaincodeLogger) Errorf(format string, args ...interface{})
(c *ChaincodeLogger) Criticalf(format string, args ...interface{})

f 형식의 로깅 API는 로그의 형식을 정확하게 제어합니다. 비 f 형식의 API는 현재 인수의 출력 표현 사이에 공백을 삽입하고 임의로 사용할 형식을 선택합니다.

현재 구현에서 shim 및 ChaincodeLogger에 의해 생성된 로그에는 타임 스탬프가 지정 되고 로거 이름 및 심각도 수준이 표시되며 stderr에 기록됩니다. 로깅 레벨 컨트롤은 현재 ChaincodeLogger가 생성 될 때 제공된 이름을 기반으로 합니다. 모호함을 피하기 위해 모든 ChaincodeLogger에는 "shim" 이외의 고유한 이름을 지정 해야합니다. 로거 이름 은 로거에 의해 작성된 모든 로그 메시지에 나타납니다. shim은 "심"으로 기록됩니다.

Go 언어 체인 코드는 SetLoggingLevel API를 통해 체인 코드 shim 인터페이스의 로깅 수준을 제어 할 수도 있습니다.

SetLoggingLevel(LoggingLevel level) - 심의 로깅 수준 제어

shim의 기본 로깅 수준은 LogDebug 입니다.

다음은 체인 코드가 LogInfo 레벨에서 로깅하는 개인 로깅 오브젝트를 작성하는 방법과 환경 변수를 기반으로 shim이 제공하는 로깅의 양을 제어 하는 간단한 예제입니다.

var logger = shim.NewLogger("myChaincode")

func main() {

    logger.SetLevel(shim.LogInfo)

    logLevel, _ := shim.LogLevel(os.Getenv("SHIM_LOGGING_LEVEL"))
    shim.SetLoggingLevel(logLevel)
    ...
}

Securing Communication With Transport Layer Security (TLS)

Securing Communication With Transport Layer Security (TLS)

패브릭은 TLS를 사용하는 노드 간의 보안 통신을 지원합니다. TLS 통신은 단방향 (서버 만) 및 양방향 (서버 및 클라이언트) 인증을 모두 사용할 수 있습니다.

Configuring TLS for peers nodes

피어 노드는 TLS 서버와 TLS 클라이언트입니다. 다른 피어 노드, 응용 프로그램 또는 CLI가 다른 피어 노드 또는 순서 지정자와 연결될 때 다른 피어 노드, 응용 프로그램 또는 CLI가 이 노드에 연결하고 후자를 피어 노드로 연결하면 전자가 됩니다.

피어 노드에서 TLS를 사용하도록 설정하려면 다음 피어 구성 속성을 설정하십시오.

  • peer.tls.enabled = true
  • peer.tls.cert.file = TLS 서버 인증서가 포함 된 파일의 정규화 된 경로
  • peer.tls.key.file = TLS 서버 개인 키가 들어있는 파일의 정규화 된 경로
  • peer.tls.rootcert.file = TLS 서버 인증서를 발급한 인증 기관(CA)의 인증서 체인을 포함하는 파일의 정규화 된 경로

기본적으로 TLS 클라이언트 인증은 피어 노드에서 TLS를 사용하도록 설정하면 해제됩니다. 즉, 피어 노드는 TLS 핸드 셰이크 중에 클라이언트 (다른 ​​피어 노드, 응용 프로그램 또는 CLI)의 인증서를 확인하지 않습니다. 피어 노드에서 TLS 클라이언트 인증을 사용하려면 피어 구성 속성 peer.tls.clientAuthRequired를 true로 설정하고 peer.tls.clientRootCAs.files 속성을 조직의 클라이언트에 대해 TLS 인증서를 발급한 CA 인증서 체인이 포함 된 CA 체인 파일로 설정합니다.

기본적으로 피어 노드는 TLS 서버 및 클라이언트로 작동 할 때 동일한 인증서 및 개인 키 쌍을 사용합니다. 클라이언트 측에 대해 다른 인증서와 개인 키 쌍을 사용하려면 peer.tls.clientCert.filepeer.tls.clientKey.file 구성 등록 정보를 각각 클라이언트 인증서와 키 파일의 정규화된 경로로 설정하십시오.

클라이언트 인증을 사용하는 TLS는 다음 환경 변수를 설정하여 활성화 할 수도 있습니다.

  • CORE_PEER_TLS_ENABLED = true
  • CORE_PEER_TLS_CERT_FILE = 서버 인증서의 정규화 된 경로
  • CORE_PEER_TLS_KEY_FILE = 서버 개인 키의 정규화 된 경로
  • CORE_PEER_TLS_ROOTCERT_FILE = CA 체인 파일의 정규화 된 경로
  • CORE_PEER_TLS_CLIENTAUTHREQUIRED = true
  • CORE_PEER_TLS_CLIENTROOTCAS_FILES = CA 체인 파일의 정규화 된 경로
  • CORE_PEER_TLS_CLIENTCERT_FILE = 클라이언트 인증서의 정규화 된 경로
  • CORE_PEER_TLS_CLIENTKEY_FILE = 클라이언트 키의 정규화 된 경로

클라이언트 인증이 피어 노드에서 활성화되면 클라이언트는 TLS 핸드 셰이크 중에 인증서를 보내야합니다. 클라이언트가 인증서를 보내지 않으면 핸드 셰이크가 실패하고 피어는 연결을 닫습니다.

피어가 채널에 조인하면 채널 구성원의 루트 CA 인증서 체인이 채널의 config 블록에서 읽히고 TLS 클라이언트 및 서버 루트 CA 데이터 구조에 추가됩니다. 따라서 피어 투 피어 통신, 피어 투 발주자 통신은 매끄럽게 작동해야합니다.

Configuring TLS for orderer nodes

orderer 노드에서 TLS를 사용하려면 다음 orderer 구성 등록 정보를 설정하십시오.

  • General.TLS.Enabled = true
  • General.TLS.PrivateKey = 서버 개인용 키가 들어있는 파일의 완전한 경로
  • General.TLS.Certificate = 서버 인증서를 포함하는 파일의 정규화 된 경로
  • General.TLS.RootCAs = TLS 서버 인증서를 발급 한 CA의 인증서 체인을 포함하는 파일의 정규화 된 경로

기본적으로 TLS 클라이언트 인증은 피어의 경우와 마찬가지로 orderer에서 해제됩니다. TLS 클라이언트 인증을 사용하려면 다음 구성 등록 정보를 설정하십시오.

  • General.TLS.ClientAuthRequired = true
  • General.TLS.ClientRootCAs = TLS 서버 인증서를 발급 한 CA의 인증서 체인을 포함하는 파일의 정규화 된 경로

클라이언트 인증을 사용하는 TLS는 다음 환경 변수를 설정하여 활성화 할 수도 있습니다.

  • ORDERER_GENERAL_TLS_ENABLED = true
  • ORDERER_GENERAL_TLS_PRIVATEKEY = 서버 개인용 키가 들어있는 파일의 완전한 경로
  • ORDERER_GENERAL_TLS_CERTIFICATE = 서버 인증서를 포함하는 파일의 정규화 된 경로
  • ORDERER_GENERAL_TLS_ROOTCAS = TLS 서버 인증서를 발급 한 CA의 인증서 체인을 포함하는 파일의 정규화 된 경로
  • ORDERER_GENERAL_TLS_CLIENTAUTHREQUIRED = true
  • ORDERER_GENERAL_TLS_CLIENTROOTCAS = TLS 서버 인증서를 발급 한 CA의 인증서 체인을 포함하는 파일의 정규화 된 경로

Configuring TLS for the peer CLI

TLS 사용 가능 피어 노드에 대해 피어 CLI 명령을 실행하는 경우 다음 환경 변수를 설정해야합니다.

  • CORE_PEER_TLS_ENABLED = true
  • CORE_PEER_TLS_ROOTCERT_FILE = TLS 서버 인증서를 발급한 CA의 인증서 체인을 포함하는 파일의 정규화 된 경로

원격 서버에서 TLS 클라이언트 인증을 사용하는 경우 위의 변수 외에 다음 변수를 설정해야합니다.

  • CORE_PEER_TLS_CLIENTAUTHREQUIRED = true
  • CORE_PEER_TLS_CLIENTCERT_FILE = 클라이언트 인증서의 정규화 된 경로
  • CORE_PEER_TLS_CLIENTKEY_FILE = 클라이언트 개인 키의 완전한 경로

피어 채널 <create | update | fetch> 또는 피어 체인 코드 <invoke | instantiate> 와 같이 orderer 서비스에 연결하는 명령을 실행하는 경우 주문자에서 TLS를 사용하는 경우 다음 명령 줄 인수도 지정해야합니다.

  • -tls
  • -cafile <orderer의 인증 코드 체인을 포함하는 파일의 완전한 경로 CA>

TLS 클라이언트 인증이 orderer에 대해 사용 가능한 경우 다음 인수도 지정해야합니다.

  • -clientauth
  • -keyfile <클라이언트 개인 키가 들어있는 파일의 완전한 경로>
  • -certfile <클라이언트 인증서가 들어있는 파일의 전체 경로>

Debugging TLS issues

TLS 문제를 디버깅하기 전에 TLS 클라이언트와 서버 측 모두에서 GRPC debug를 활성화 하여 추가 정보를 얻는 것이 좋습니다. GRPC debug를 사용하려면 CORE_LOGGING_GRPC 환경 변수를 DEBUG로 설정하십시오.

클라이언트 쪽에서 remote error: tls: bad certificate 오류 메시지가 표시 되면 일반적으로 TLS 서버에서 클라이언트 인증을 사용하고 서버가 올바른 클라이언트 인증서를 받지 못했거나 신뢰할 수없는 클라이언트 인증서를 받았다는 의미입니다. 클라이언트가 인증서를 보내고 피어 또는 orderer 노드가 신뢰하는 CA 인증서 중 하나가 서명했는지 확인하십시오.

체인 코드 로그에 remote error: tls: bad certificate 오류 메시지가 표시되면 Fabric v1.1 이상에서 제공되는 체인 코드 심을 사용하여 체인 코드가 빌드되었는지 확인하십시오. chaincode에 shim의 판매자 된 사본이 없으면 chaincode 컨테이너를 삭제하고 해당 피어를 다시 시작하면 현재 shim 버전을 사용하여 chaincode 컨테이너를 다시 작성합니다. 체인 코드가 이전 버전의 shim을 제공했다면, vend -vendored-shim 을 업그레이드 하는 방법에 대한 문서를 검토하십시오.

Bringing up a Kafka-based Ordering Service

Bringing up a Kafka-based Ordering Service

Caveat emptor

이 문서는 독자가 일반적으로 Kafka 클러스터와 ZooKeeper 앙상블을 설정하는 방법을 알고 있다고 가정합니다. 이 가이드의 목적은 Hyperledger Fabric ordering 서비스 노드 세트(OSNs)가 Kafka 클러스터를 사용하고 블록 체인 네트워크에 ordering 서비스를 제공하기 위해 취해야 할 단계를 식별하는 것입니다.

Big picture

각 채널은 Kafka의 별도의 단일 파티션 주제에 매핑됩니다. OSN이 Broadcast RPC 를 통해 트랜잭션을 수신 하면 브로드캐스트 클라이언트가 채널에 쓸 수 있는 권한이 있는지 확인한 다음 해당 트랜잭션을 카프카의 적절한 파티션으로 중계합니다. 이 파티션은 수신된 트랜잭션을 로컬 블록으로 그룹화하고 로컬 원장에서 이를 유지하며 Deliver RPC를 통해 클라이언트를 수신하는 OSN에 의해 ​​소비됩니다. 저수준에 대한 자세한 내용은 describes how we came to this design 문서를 참조하십시오. 그림 8은 위에 설명 된 프로세스의 개략적인 표현입니다.

Steps

K와 Z 를 Kafka 클러스터와 ZooKeeper 앙상블의 노드 수로 각각 설정합니다. :

  1. K는 최소한 4로 설정해야합니다 (아래 4 단계에서 설명 하겠지만, 이것은 고장 내결함성을 나타내기 위해 필요한 노드의 최소 수입니다. 즉, 4 개의 브로커를 사용하면 1 개의 브로커가 다운 될 수 있습니다. 채널은 계속해서 쓰기 및 읽기가 가능하며 새로운 채널을 만들 수 있습니다.)
  2. Z는 3, 5 또는 7 중 하나입니다. 스플릿 브레이브 시나리오를 피하기 위해서는 홀수이어야하며 단일 실패 지점을 피하려면 1보다 커야합니다. 7 개의 ZooKeeper 서버를 초과하는 것은 과잉으로 간주됩니다.

그런 다음 다음과 같이 진행하십시오.

  1. 주문자 네트워크의 기원 블록(genesis block)에 카프카 관련 정보를 암호화하십시오. configtxgen을 사용중인 경우 configtx.yaml을 편집하거나 시스템 채널의 기원 블록(genesis block)에 대한 사전 설정된 프로필을 선택하여 다음과 같이하십시오.
    1. Orderer.OrdererTypekafka로 설정됩니다.
    2. Orderer.Kafka.Brokers에는 클러스터에 있는 두 개 이상의 Kafka 중개인의 주소가 IP:port으로 들어있습니다. 이 목록은 완전 할 필요는 없습니다. (이들은 부트 스트랩 브로커입니다.)
  2. Orderers 최대 블록 크기를 설정하십시오. 각 블록에는 대부분 Orderer.AbsoluteMaxBytes 바이트(헤더 제외)가 있으며 configtx.yaml에 설정할 수 있습니다. 여기에서 선택한 값을 A로 지정하고 기록해 두십시오 - 6 단계에서 Kafka 중개인을 구성하는 방법에 영향을 줍니다.
  3. Orderers 기원 블록(genesis block)을 만듭니다. configtxgen을 사용합니다. 위의 3 단계와 4 단계에서 선택한 설정은 시스템 전체의 설정입니다. 즉, 모든 OSN에 대해 네트워크 전체에 적용됩니다. 기원 블록(genesis block)의 위치를 ​​기록하십시오.
  4. Kafka 클러스터 Kafka brokers를 적절하게 구성하십시오. 모든 카프카 중개인은 다음과 같은 키를 구성해야합니다.
    1. unclean.leader.election.enable = false - 데이터 일관성은 블록 체인 환경에서 핵심입니다. 동기화된 복제 세트 외부에서 채널 리더를 선택할 수 없거나 이전 리더가 생성한 오프셋을 덮어 쓸 위험이 있습니다. 결과적으로 orderer가 생산하는 블록 체인을 다시 작성합니다.
    2. min.insync.replicas = M -  1 < M < N와 같은 M 값을 선택하십시오(아래 default.replication.factor 참조). 데이터는 최소한 M개의 복제본에 기록 될 때 커밋된 것으로 간주됩니다 (동기화 후 동기화 된 것으로 간주되고 동기화 된 복제 집합 또는 ISR에 속함). 다른 경우, 쓰기 조작은 오류를 리턴합니다. 그때:
      1. 채널 데이터가 기록되는 N개까지의 N-M 복제본을 사용할 수 없게 되면 작업이 정상적으로 진행됩니다.
      2. 더 많은 복제본을 사용할 수 없게 되면 Kafka는 M의 ISR 집합을 유지할 수 없으므로 쓰기 허용을 중지합니다. 문제없이 작업을 읽습니다. 채널은 M개의 복제본이 동기화 될 때 채널에 다시 쓸 수 있게 됩니다.
    3. default.replication.factor = N - 여기서 N < K인 값 N을 선택합니다. N의 복제 인수는 각 채널이 N개의 브로커에 복제된 데이터를 갖게됨을 의미합니다. 이들은 채널의 ISR 세트 후보입니다. 위의 min.insync.replicas section에서 언급했듯이 모든 브로커가 항상 사용 가능해야하는 것은 아닙니다.  N 브로커보다 적으면 채널 생성을 진행할 수 없으므로 NK보다 반드시 작게 설정해야합니다. 따라서 N = K로 설정하는 경우 단일 브로커가 중단된다는 것은 블록 체인 네트워크에 새로운 채널을 만들 수 없다는 것을 의미합니다. ordering 서비스의 오류 방지 기능은 존재하지 않습니다. 위에서 설명한 것을 바탕으로, M과 N의 최소 허용 값은 각각 2, 3입니다. 이 구성은 앞으로 나아갈 새로운 채널을 생성하고 모든 채널이 계속 쓰기 가능하도록 합니다.
    4. message.max.bytes 및 replica.fetch.max.bytes는 위의 4단계의 Orderer.AbsoluteMaxBytes에서 선택한 A 값보다 큰 값으로 설정되어야합니다. 헤더를 설명할 버퍼를 추가하십시오. 1 MiB가 충분합니다. 다음 조건이 적용됩니다. : Orderer.AbsoluteMaxBytes < replica.fetch.max.bytes <= message.max.bytes  (완전성을 위해 message.max.bytes는 기본적으로 100 MiB로 설정되는 socket.request.max.bytes 값보다 작아야 하며, 100 MiB보다 큰 블록을 사용하려면 fabric/orderer/kafka/config.go에 있는 brokerConfig.Producer.MaxMessageBytes의 하드 코딩된 값을 수정하고 소스에서 이진 파일을 다시 작성해야 합니다. 이것은 권장되지 않습니다.)
    5. log.retention.ms = -1. ordering 서비스가 Kafka 로그의 가지 치기에 대한 지원을 추가 할 때까지는 시간 기반 보존을 비활성화하고 세그먼트가 만료되지 않도록해야합니다. (크기 기반 보존 - log.retention.bytes -는 본문 작성 시점에 Kafka에서는 기본적으로 비활성화되어 있으므로 명시적으로 설정할 필요가 없습니다.)
  5. Orderers 각 OSN을 기원 블록(genesis block)으로 향하게 하십시오. General.GenesisFileorderer.yaml에서 편집하여 위의 5 단계에서 생성된 기원 블록(genesis block)을 가리키도록 합니다. (그 동안 YAML 파일의 다른 모든 키가 적절하게 설정되었는지 확인하십시오.)
  6. Orderers 폴링 간격 및 타임 아웃을 조정합니다. (선택 단계.)
    1. orderer.yaml 파일의 Kafka.Retry 섹션을 사용하여 메타 데이터/제작자/고객 요청의 빈도와 소켓 시간 초과를 조정할 수 있습니다. (이들은 Kafka 제작자 또는 소비자에게 기대되는 모든 설정입니다.)
    2. 또한 새 채널이 생성되거나 기존 채널이 다시 로드 될 때 (orderer가 방금 다시 시작된 경우) orderer는 다음과 같은 방법으로 Kafka 클러스터와 상호 작용합니다.
      1. 채널에 해당하는 Kafka 파티션을위한 Kafka 제작자 (작성자)를 만듭니다.
      2. 해당 생성자를 사용하여 해당 파티션에 no-op CONNECT 메시지를 게시 합니다.
      3. 해당 파티션에 대한 Kafka 소비자 (판독기)를 만듭니다. 이러한 단계 중 하나라도 실패하면 반복되는 빈도를 조정할 수 있습니다. 구체적으로 그들은 Kafka.Retry.ShortInterval의 총합을 위해 Kafka.Retry.ShortInterval마다 다시 시도될 것이며, Kafka.Retry.LongInterval을 성공할 때까지 Kafka.Retry.LongTotal의 총합을 구하기 재시도합니다. 위의 모든 단계가 성공적으로 완료 될 때까지 orderer는 채널에 쓰거나 채널에서 읽을 수 없습니다.
  7. SSL을 통해 통신할 수 있도록 OSN 및 Kafka 클러스터를 설정합니다. (옵션 단계이지만 적극 추천합니다.) 방정식의 Kafka 클러스터 측면에 대해서는 Confluent 가이드 문서를 참조하고 그에 따라 모든 OSN에서 Kafka.TLS의 키를 orderer.yaml로 설정하십시오.
  8. ZooKeeper 앙상블, Kafka 클러스터, ordering 서비스 노드 순서로 노드를 가져옵니다.

Additional considerations

  1. 기본 메시지 크기. 위의 4 단계 (Steps 섹션 참조)에서 Orderer.Batchsize.PreferredMaxBytes 키를 설정하여 원하는 블록 크기를 설정할 수도 있습니다. 상대적으로 작은 메시지를 처리 ​​할 때 Kafka는 높은 처리량을 제공합니다. 1 MiB보다 크지 않은 값을 목표로 삼는다.
  2. 환경 변수를 사용하여 설정을 무시합니다. Fabric과 함께 제공되는 샘플 Kafka 및 Zookeeper Docker 이미지 (images/kafka 및 images/zookeeper 참조)를 사용하는 경우, 환경 변수를 사용하여 Kafka 브로커 또는 ZooKeeper 서버의 설정을 무시할 수 있습니다. 구성 키의 점을 밑줄로 바꾸십시오 - 예를 들어 KAFKA_UNCLEAN_LEADER_ELECTION_ENABLE=false를 지정하면 unclean.leader.election.enable의 기본값을 무시할 수 있습니다. 로컬 구성에 대한 OSN에도 동일하게 적용됩니다 ( 즉, orderer.yaml에서 설정할 수 있는 항목). 예를 들어 ORDERER_KAFKA_RETRY_SHORTINTERVAL=1s이면 Orderer.Kafka.Retry.ShortInterval의 기본값을 재정의할 수 있습니다.

Kafka Protocol Version Compatibility

패브릭은 sarama 클라이언트 라이브러리와 공급 업체를 사용하여 Kafka 0.10에서 1.0까지 지원하지만 아직 이전 버전에서 작동하는 것으로 알려져 있습니다.

orderer.yamlKafka.Version 키를 사용하여 Kafka 클러스터의 브로커와 통신하는 데 사용되는 Kafka 프로토콜 버전을 구성할 수 있습니다. Kafka 브로커는 이전 버전의 프로토콜과 역 호환됩니다. Kafka 브로커의 이전 프로토콜 버전과의 이전 호환성으로 인해 Kafka 브로커를 새 버전으로 업그레이드하는 경우 Kafka.Version 키 값을 업데이트할 필요는 없지만 Kafka 클러스터는 이전 프로토콜 버전을 사용하는 동안 성능이 저하 될 수 있습니다.

Debugging

General.LogLevel을 DEBUG로 설정하고 orderer.yamlKafka.Verbose를 true로 설정합니다.

Example

Sample Docker 위의 권장 설정으로 인라인 구성 파일을 작성하려면 fabric/bddtests 디렉토리 아래에 있습니다. dc-orderer-kafka-base.ymldc-orderer-kafka.yml를 찾으십시오.