사실 Leader election 은 가장 단순하게는 주변 노드들의 이름을 리스트로 가지고 있다가, 이름 순으로 그 다음 노드가 그냥 리더가 되는 느낌으로 구현하면 매우 단순하긴 한데, (Distributed Systems 책들에 소개되는 수준의 Bully algorithm, Ring algorithm 등은 실용적으로 사용하기에는 다소 심플하다.) Split brain 때문에 Term(epoch) 단위 동안에 가장 다수의 투표를 받은 노드가 선출되는등의 기술(?) 이 들어가며 복잡해지곤 하며...문제를 완벽히 해결하기가 쉽지는 않다. 아래 글에서는 하이퍼레저 패브릭상에서 발생되는 2가지 주요 분산합의 상황에서의 리더 선출에 관해 대략적으로 끄젹 꺼려 보겠다. 

* 이 문서는 앞으로 실제 패브릭 구현 상에서의 알고리즘으로 꾸준하게 수정 될 예정이다.

Gossip Protocol 


(gossip protocol 은 주변에 랜덤하게 자신이 가진 최신 정보를 뿌려주고, 랜덤으로 선택된 피어에게 최신 정보를 요청하는 주로 push-pull 모델을 이용하여 전체 네트워크의 상태를 일치시키는 알고리즘이다. 이때 최신정보는 항상 리더로 부터 시작된다. 리드 선출에 관해 공개된 상세한 정보는 없으며, 코드를 봐야 이해 할 수 있다. 공식문서에는 그냥 static으로 설정하거나 dynamic으로 설정 할 수 있다 정도~)

- 상태는 Leader , Follower 2가지이다.
- ID 문자열의 사전상 순서로 우선순위를 가진다. 
- term id , epoch id 란 개념이 없다. 
- 하나의 membership view에서는 하나의 리더를 가진다.
- 네트워크가 분리되면 분리 된 수 만큼 리더를 가지며, (각자 orderer에게 블록 요청) 합쳐지면 하나로 돌아 온다.
- Leadership declaration (내가 리더다) 와 Proposal (내가 리더가 되고 싶어) 메세지가 있다. 
- Leadership declaration (내가 리더다) 를 주기적으로 보내며, 이것을 못받은 Follower는 리더선출에 돌입하며, 이렇게 네트워크는 분리된다..나중에 더 낮은 ID를 가진 노드에서 Leadership declaration 받게되면 리더 자리를 물러나게 되며 자연스럽게 네트워크는 합쳐진다.

 Startup():
 	wait for membership view to stabilize, or for a leadership declaration is received
      or the startup timeout expires.
	goto SteadyState()

// 3 possible ways to stabilize
//   - After a period of time, check whether the number of peer lists before and after is consistent.
//     if they are consistent, it indicates stability.
//   - If a leader is elected, it's also stable
//   - Otherwise if timeout, consider it stable and vote for new leader from proposal set


 SteadyState():
 	while true:
		If leaderKnown is false:
 			LeaderElection()
		If you are the leader:
			Broadcast leadership declaration
			If a leadership declaration was received from
 			a peer with a lower ID,
			become a follower
		Else, you're a follower:
			If haven't received a leadership declaration within
 			a time threshold:
				set leaderKnown to false

 LeaderElection():
 	Gossip leadership proposal message
	Collect messages from other peers sent within a time period
	If received a leadership declaration:
		return
	Iterate over all proposal messages collected.
 	If a proposal message from a peer with an ID lower
 	than yourself was received, return.
	Else, declare yourself a leader

 

RAFT


RAFT도 위와 조금 비슷하긴 한데 차이점은 우선순위(ID문자열 기준)가 없고, Term (epoch) 이라는 1씩 증가하는 공통적으로 공유하는 상태가 있으며 Candidate 상태가 추가 되었다. 특히 RAFT은 Gossip에 비해 split brain 문제를 방어하기 위해서 좀 더 복잡 한 면이 있으며, 리드선출 기간이 피어마다 랜덤하게 설정되서 먼저 자기를 투표해 달라고 하는 놈이 있으면 그 놈에게 그냥 투표해 주기 때문에 결국 그 피어가 리더가 될 확률이 높아진다. 과반수로 부터 표를 받으면 자기가 리더인것을 확정짓고 리더로써의 하트비트를 날려 주게 된다. 만약 운이 안좋아서 비슷한 시간에 2개의 피어가 후보자가 될 경우, 표를 과반 수 이상 못받으면 다음 Term으로 넘어간다. 즉 split brain이 발생하지 않는다. (비잔틴은 없다라고 가정한다) 

두가지 타임아웃이 있다:  heartbeat timeout (리더), election timeout (팔로워) heartbeat타임아웃은 election timeout보다 주기가 짧아야한다. election timeout은 그보다 큰 제한하에  각 노드별로 랜덤값 

1. When is it started 

     - 리더로 부터 정해진 시간안에
       정식 메세지 , 하트비트 ,  candidate 로 부터의 vote 메세지중 아무것도 못받은 경우   


2. How to elect leader 

     -  리더로 부터 아무것도 못받은 각 못받은 노드는 자신의 election timeout (노드별 랜덤) 이 발생하면 상태를 candidate로 변경하고 term + 1하고 스스로에게 투표한후 나머지 follower들에게 투표를 요청 한다.
     -  election timeout  이 발생되지 않은 follow 노드는 투표를 해 준다. ( 동일 term에 한해 1표, Candidate는 다른 Candidate에게 투표 안함) 
     - follower는 투표해주고 election timeout을 리셋한다. (term도 갱신된다) 
     - 과반수의 투표를 받으면 상태를 leader로 바꾸고 리더 역할을 한다. 
     - 과반수를 못받으면 다시 투표를 요청한다.
     - election timeout이 거의 비슷한 노드가 동시에 candidate 되었을 경우 발생 할 수 있는 split brain 에서 과반수를 받은 candidate가 없어서 leader가 선출이 안됬을 경우, re election을 진행해서 랜덤하게 새로 정해진 (term 마다 항상 새로 선정됨) election timeout을 기반으로 다시 leader 선출을 진행한다. 이때 follower 중 하나가 election timeout이 빨리 도달하면, 기존 candidate를 재치고 term+1을 통해 리더가 될 수도 있다. 
     - term이 높은 메세지가 오면 follower로 돌아간다. 

http://thesecretlivesofdata.com/raft/
 
리더 선출에 대한 간단히 표로 정리 해보았다.

 

 

페이스북 :  엔터프라이즈 블록체인 그룹 

 

 

PBFT (Practical Byzantine Fault Tolerance)

BFT는 분산된 노드들간에 동일한 상태를 유지하기 위한 방식으로, 악의적인 노드가 있는 것을 전제로 합니다. 여기서 악의적인 노드의 최대수는 N = 3f+1입니다.

N : 전체노드 개수 
f   : 악의적인 노드 개수 

따라서 4개의 노드에서는 1개는 악의적인 노드라도 생관없다는 의미입니다. 7개노드에서는 최대 2개.아래 이미지에서는 4개의 노드에서 최대1개의 비잔틴(악의적노드)가 있다고 치고 합의 단계에 대해 설명해보면 

Request 단계

클라이언트는 상태변경을 위한 요청 (REQUEST, o, t, c)sc 을 대표 노드에 보냅니다. 참고로 이 대표노드(Primary) 또한 비잔틴이 될 수 있으며 그땐 새로운 대표노드를 선출 하게 됩니다.

Pre-Prepare 단계

대표노드는 다른 모든 노드들에게 ((PRE-PREPARE, v, n, d)sp, m)이라는 메세지를 전파합니다.
이 상태에서는 최신상태를 일단 가지고 있게 됩니다만 이게 옳은 것인지는 판단 할 수 없습니다.
그리고 n은 순서를 나타내는데 오더링에 대한 합의를 한다고 볼 수 있습니다. 
 

Prepare 단계

 자신이 받은 최신 상태정보를 기반으로 (PREPARE, v, n, d, i)si라는 메세지를 클러스터 내의 모든 노드들에게  전파합니다. 여기서 다른 노드들의 PREPARE 메세지 2f를 받으면, Prepared가 되서 넘어갑니다. 이 단계에서는 오더링을 확신하게 되고 커밋 준비를 할 수 있게 됩니다. 근데 여기서 다시 봐야하는 부분이 2f인데요, 자기 빼고 3개중에 2개의 연락만 받으면 ㅇㅋ 라는 겁니다. 즉 나머지 1개가 비잔틴이건 아니건 상관없는거죠. 비잔틴은 아니지만 그 놈은 좀 헤롱헤롱 대서 처리가 좀 늦는다. 이 놈이 Primary가 된다면? 또한 PBFT를 접한 사람들이 가장 궁금하게 생각하는게 나오는데 , 바로 이 지점에서 클라이언트에게 리턴하면 왜 안되냐는 거죠. 어느 정도 합의를 이끌어 냈잖습니까? 이런 부분들에 대해서는 각자도생하는것으로 합시다. 하나씩 그려보면 안되는 경우를 도출해 낼 수 있을 겁니다. (합의에 3단계가 필요한 이유

Commit 단계

위에서 PREPARE 메세지 2f를 받으면,  (Commit, v, n, D(m), i)si라는 메세지를 전파할 수 있게 됩니다. 그리고 다른 노드들로 부터 Commit메세지를 받아서 자기포함 2f+1개(논문12p)를 받으면 커밋합니다. 

Reply 단계

                 

Commit 검증에 성공한 노드들은 클라이언트에게 응답을 보내주고 f+1개(논문8p) 이상의 똑같은 응답

을 받으면 클라이언트는 보낸 메세지가 성공적으로 분산노드들의 상태를 변경을 했다는 것을 인지합니다. 이런 합의 로직 이외에도 대표노드를 바꾸기 위한 view change,  메세지 prunning을 위한 checkpoint (watermark) 등에 관련된 내용이 있습니다.

간략히 아래와 같은 도식으로 이해 하실 수 있습니다. (PBFT 논문과는 다르게 Client는 모든 노드에게 메세지를 전달합니다. 이는 Primary가 헛수고 하는 것을 막기 위함으로 자신이 받았는데도 불구하고 Primary 로 부터 Pre-Prepare 메세지가 안날라오는 경우를 대비하기 위함입니다) 



아래부터는 블록체인 계에서 사용하는 PBFT 계열의 합의에 대한 간략한 소개 입니다.


Tendermint

사실상 아래 나오는 모든 알고리즘들의 부모격으로써 PoW 말고 PBFT를 이용하여 블록체인을 구성하기 위해서 처음 등장한 개념으로, 무허가형의 지분증명(PoS)기반의 보안 메커니즘에서 수백개의 노드로 활장 할 수 있는 BFT 기반의 프로토콜로써, 

소규모로 구성된 노드들말고 WAN용 광역네트워크에서도 PBFT를 활용할 수 있게 연구하였습니다. 

텐더민트에 관련된 글을 보면 항상 나오는 그림으로써, 위의 PBFT 글을 읽었다면 간단히 이해 할 수 있는 내용입니다. 녹색박스를 보면 Propose -> Pre-Prepare, Prevote Block -> Prepare , Precommit Block -> Commit 와 매칭됨을 알 수 있습니다. 그리고 

아래를 보면 PBFT에 대한 껄쩍지근했던 궁금증을 쉽게 해소 할 수 있습니다.

텐더민트 합의에 3단계가 필요한 이유
텐더민트 합의에 락이 필요한 이유


* Tendermint 에서 대표node 들을 어떻게 선출하는지에 관해서는 조사 안함.  

NCCU BFT

 대만의 Chengchi University 블록체인 그룹에서 텐더민트에서 영감을 받아 만든 프로젝트로써, 이더리움의 합의를 BFT를 통해서 하는 허가형 향으로 변경하기 위한 프로젝트입니다. 메세지로써 블록이 노드들에게 전달되며, 커밋 페이즈에서 블록(트랜잭션)은 실행되고 Insert 되게 됩니다. 




Hyperledger Fabric - SIEVE

PBFT에 체인코드 실행과정과 블록커밋 과정이 제일 앞단과 마지막 커밋 구간에 포함된 것입니다.  
이 얘기는 1.0 이후의 E-O-V 모델을 떠올릴만 한데. 즉 Endorsing 과정이 앞에 선두에 있으며, 그 과정이 끝나면 PBFT를 시작하고 마지막에 커밋한다는 것입니다. 이것은 Full Go언어 기반의 체인코드가 비결정적으로 실행 할 수 있다는 이야기인데, 앞에서 거를 수 있기 때문입니다. 

 

Hyperledger Fabric - Simple BFT 

하이퍼레저가 1.0에서 PBFT를 버리고, 카프카 기반으로 오더링 시스템으로 변한 후에도 패브릭 측은 BFT에 대한 추가 모듈을 개발하는것에 대한 끈은 놓지 않고 있습니다. 일례로 2.0에서 나올 예정인 RAFT도 결국 BFT를 위한 기반이라고 말하고 있는 정도니... (굳이 외부시스템(카프카,주키퍼)를 사용 할 필요없이) 위의 링크의 Simple BFT는 그러한 패브릭이 BFT을 이러한식으로 만들겠다라는 짧은 설계 방향에 대해서 서술해 놓고 있는데 PBFT의 단순화 버전입니다. 개인적으로는 

카프카 대체제로는 RAFT로 충분하고 BFT계열은 간단하든 복잡하는 오버스펙이라 시작할맘도 없을 거 같습니다.참고로 JP모건 애들이 만드는 콘소시엄체인은 RAFT랑 IstabulBFT 라는것을 쓰는데 패브릭도 BFT계열을 오더링만 하는데 사용 할 바엔 E-O-V 프로세스를 폐기하는게 낫다고 봅니다. 아마 거기 아키텍트도 똑같은 생각하고 있을듯..ㅎㅎ 

(추가작성예정)

 

Hyperledger Fabric - MinBFT

 대체제로 PBFT와 똑같은데, Pre-Prepare 과정이 생략됬다고 생각하면 된다. 따라서 페이즈가 2로 줄었고 2f + 1이면 합의를 이룰수 있다. 이는 Secure Hardware (Intel Software Guard Extensions (SGX)) 를 통한 Primary Node의 안전성을 보장함으로 얻어진다. 근데 SGX 해킹된다던데.... 업데이트가 되었는지는 잘..

 

Istanbul BFT (IBFT)

JP Morgan의 콘소시엄형 블록체인인 GoQuorum (IBFT1.0) 과 ethereum 기반의 Hypereledger besu(GoQuorum의 IBFT1.0을 개선하여 IBFT2.0업그레이드한 버전)에서 채택하여 주목받은 BFT계열 합의로써, 기본적으로 PBFT의 형식을 따라가며 블록을 모아서 전송한다는 개념이 추가되었습니다.  주요 차이점은 Client가 분명하지 않으며, 합의 노드들에는 아무 클라이언트들이 요청을 보낼 수 있으며, 합의노드들은 서로의 존재에 대해 알고 있으며 (Public key 공유) 리더(IBFT에서는 Proposer 노드)는 트랜잭션을 모아 블록을 검증 (논스관련,클라이언트 서명관련, Besu경우 가스관련등등) 하고 만들어서 전파합니다. Prepare단계를 거쳐 Commit 단계에서 블록 커밋을 하며, 비 합의노드에도 블록은 전파됩니다. 각 합의노드들의 인증이 모여서 블록 헤더에 extraData로 들어가게 되며, (인증받은 블록이란걸 검증하기 위함, 따라서 스스로 검증가능하다고 말해 집니다)  Validator는 블록에 서명을 하고 insert 를 하게 되는데 이렇게 되면 블록해쉬가 달라지기 때문에 서명한 부분은 블록해쉬에서 제외 하기도 합니다. 한라운드의 합의가 끝마치게 되면 Validators(Backups)들은 새로운 Proposer를 골라서 새로운 블록을 만들 책임을 지웁니다. 보통 라운드로빈으로 하며 이런 Validators들은 그룹멤버쉽을 통해 새로운 멤버가 추가되거나 삭제 될 수 있으며 각각의 투표는 블록헤더에 기록됩니다.

(Hyperledger besu - IBFT2.0 에서의 트랜잭션 검증도)



RBFT 

간략하게 설명하면 여러개의 BFT 인스턴스들을 생성해서 병렬처리하며, 하나의 인스턴스에서 오더링 하는 구조 입니다. (추가 작성중..) 


Mir-BFT

간략하게 설명하면 트랜잭션의 모음을 몇개의 버켓으로 나누어서 각 버켓을 각 노드들에게 맞기는데 , 각 노드들은 리더가 됩니다. 즉 리더가 여러개이며, 이 버켓들이 병렬적으로 처리되고 마지막에 순서를 갖춰서 커밋되는 구조 입니다. 초기 서명검증을 병렬적으로 할 수 있기 때문에 속도 향상을 꽤 할 수 있습니다.

 

공통

* 모든 방법에는 가쉽네트워크를 통한 블록싱크가 추가되야 한다. (패브릭처럼 합의 네트워크 말고 합의 네트워크의 결과를 받아서 블록체인 공유를 하는 시스템이라면 필요 없고~) 
* 패브릭의 체인코드의 Go코드는 비결정적인데 이를 해소할 방안은 없다. (SIEVE가 가능한데...성능상에 불리하며, VM레이어를 만들어 넣어서 결정적으로 바꿀 수 밖에..)


그 밖에도)

* 사실 EOS도 DPos 합의 아래 계층에서 BFT 변형을 사용한다.
* 스텔라도 BFT 변형을 사용한다. 


부록)

Clique (PoA) 알고리즘 

Hyperledger Besu에서 IBFT 말고 사용 할 수있는 합의 알고리즘. (Go etheurem버전도 있음)  
3라운드인 PBFT계열에 비해서 1라운드이다. 따라서 BFT계열보단 빠르다. (추가 작성 중..) 

aBFT (asynchronous byzantine fault tolerance) 
Hedera Hashgraph에서 사용하는 컨센서스 알고리즘으로 BFT계열 알고리즘 중에서는 가장 속도가 빠를 듯 하며, 그 영향력으로 Hyperledger fabric의 ordering 과 Corda 의 notary 및 기타 엔터프라이즈 블록체인등의 합의 알고리즘으로 포함될 가능성이 크다. 


PS)
개인적 의견으론 Permisioned BlockChain에서는 그냥 RAFT를 사용하는게 좋지 않을까 한다. 
비교적 단순하고, 비잔틴은 없다고 가정하므로 성능이 PBFT계열보단 훨씬 빠르다. 
Hyperledger Fabric도 GoQuorum도 RAFT가 디폴트이다. Besu는 IBFT2.0이지만 RAFT를 지원해야 하지 않을까? 

FastFabric: Scaling Hyperledger Fabric to 20,000 Transactions per Second

위 논문에 대한 저자와의 질문/답변을 공개합니다.



Question to U.Waterloo

Improvement 1: Orderer - Seperate transaction header from payload\

- You stated that we should reduce the amount of data sent from Orderer to Kafka by keeping the RWSet at the Orderer and send only the transaction's header to Kafka
- This works well when there's only one Orderer, but in case there's multiple Orderers to distribute load, how can the Orderer that made the block retrieves the body of transactions from the other Orderers?

Improvement 2: Orderer - Process transactions in parallel

- We think it's a good idea to distribute transactions into multiple threads inside Orderer as this utilizes hardware more efficiently
- However the disruptor pattern (https://lmax-exchange.github.io/disruptor/) maybe faster for this task. What are your thoughts on applying this pattern?

Improvement 3: Peer - Replacing the world state database with a hash table

- As we understood, you wanted to replace LevelDB with a completely in-memory lightweight structure like a hash table. We think this is a good improvement, but it comes with its own problems:
- What if the stateDB grows in size to be more than the machine's memory?
   @There must be a mechanism to save memory to disk, change the hardware and boot up the node a again
   @Physically upgrade the node in this way cost a lot of time and resources
- What if the node goes down suddenly? All data stored in memory would be lost, whereas with LevelDB it would be recovered partly from disk.

Improvement 4: Peer- Store blocks using a cluster

- As we understood, you suggest peers should store files in a Hadoop or Spark cluster
- We think this will greatly increase the complexity of the Peer with little benefit, since State DB storage has more impact on TPS than block storage. Do you have any other reason for this suggestion than to increase block write speed?

Improvement 5: Peer - Separate commitment and endorsement

- We agree with splitting committer and endorser into different servers since this will reduce context switching.
- We will make the endorser's DB a read-only replica of the committer's State DB as designed after Improvement 3.
- This approach comes with committer - endorser synchronization overhead (due to the need to use networking to synchronize states). We think more testing is needed to see if this overhead is worth the benefits.

Improvement 6: Peer - Parallelize validation

- From what we've read, this mean parallelize packet consistency check, signature check an RWSet correctness check.
- We see there's a potential for double spending when we process transactions to the same account in parallel. Do you have any solution for this without impacting performance?
- Also, concurrent processing comes with context switching overhead, will this be a problem when the system's under load?
- We intend to offload signature verification to hardware using FPGA or ASIC, do you think this will result in good improvements in processing speed?

Improvement 7: Peer - Cache marshaled blocks

- We mostly agree with this since this make the cache more versatile and reduce memory allocation.
- We will perform benchmark on this to see how much performance improvements can be gained while not increasing the complexity of the system.

Response from U.Waterloo

  1. We found that Kafka got exorbitantly slower for bigger message sizes. That is why we split of the body from the tx header. For multiple orderers, each would need to broadcast their tx bodies to other orderers out of band of Kafka, which we found to be faster in preliminary tests, but we didn’t fully implement the broadcast. Note that this might be obsolete now that Fabric is using Raft.
  2. I’m not very familiar with the disruptor, but it seems to me that this is an orthogonal optimization. Currently, all orderer cores but one are idle, so we definitely need to optimize for concurrent execution. It seems to me that the disruptor is simply managing access to the tx queue. Therefore it would need to be tested if the disruptor is faster than using a go channel for this.
  3. For most reasonable workloads a peer’s memory should be able to store billions of keys in memory. If this is not enough, some paging mechanism would need to be implemented, but we did not address this in our paper. Peers are still writing to disk, they just outsource the task to a secondary storage server. Therefore the latest permeated state could be recovered from there. We did not check if Fabric’s recovery mechanisms still work with the external storage, but it should be “relatively” easy to reroute recovery to the storage server.
  4. We suggest Hadoop or Spark as a possibility to be able to easily do data analytics on the peer backend. However, it is not necessary and in our proof of concept implementation we still use LevelDB (the storage server simply has to catch up to the fast peer whenever it is not running at maximum throughput)
  5. After implementing all our improvements, the throughput was still CPU bound (crypto computations), so we didn’t feel the network overhead yet.
  6. In FastFabric, we only parallelize the crypto verification, RWset correctness validation is still done sequentially to prevent double spending. In our most current work (https://arxiv.org/abs/1906.11229) we add a tx dependency analyzer to be able to parallelize RWset correctness validation for independent txs as well. I think offloading crypto to specialized hardware is the way to go forward to increase performance further.
  7. Using a unmarshalling cache as described in the paper is a workaround for better performance so we didn’t need to completely rewrite Fabric. In our most current implementation, each block is caching it’s own unmarshalled data, so we don’t need a centralized cache anymore (so no potential locking issues with multiple threads reading/writing blocks). Ideally, the unmarshalling would happen directly at the network interfaces and, internally, Fabric would only deal with domain model objects.

 

페이스북 :  엔터프라이즈 블록체인 그룹 

엔터프라이즈향 블록체인 비교 


* fabric과 Goquorum등 모든 컨소시엄 블렉체인의 사용예에서 어떻게 거버넌스를 이루어서 어떻게 사용했다라는 구체적인 기술 정보 및 비용감소에 대한 결과 정보가 부족해서 아쉽다. (사용 결과에 대한 효율 증가 분석표같은건 기대도 안함) 

*
컨소시엄 블록체인을 진짜 컨소시엄을 해서 제대로 합의하고 견제하면서 하려면 Fabric을 사용해야 하는게 좋으며 (기능셋이 많다.)  좀 간략히 사용하려면 quorum이나 Besu중 아무것이나 선택해도 된다. Corda는 최근 거의 사용되지 않는 듯하며, CDBC쪽에서나 소식이 들리는 듯 하다.

* 성능의 경우 체감상 예상외로 Fabric이 빠른데.. (Fabric  > GoQuorum > Besu) 전체 구조상으로는 동일 RAFT컨센서스 기준으로 패브릭이 단계가 더 많으므로 (E-O-V) 불리하지만, 이더리움 계열 시스템들은 (besu, quorum) 머클패트리샤트리와 EVM 구조를 그대로 사용하고, Gas가 큰 의미가 없음에도 사용되는 Gas비용계산등 퍼블릭체인의 유산들 때문에 성능 문제가 생겼으리라 생각된다

Hyperledger Besu 성능) 
https://www.hyperledger.org/blog/2020/08/06/hyperledger-besu-1-5-performance-enhancements

Quour
m성능)
https://www.sciencedirect.com/science/article/pii/S209672092100021X

Fabric 성능) 
https://arxiv.org/pdf/1901.00910.pdf
https://medium.com/coinmonks/hyperledger-fabric-blockchain-performance-benchmark-using-hyperleger-capiler-66d9a9af5cce
https://arxiv.org/pdf/1805.11390.pdf


체크1)
Hyperledger Fabric에서는 기본적으로 네트워크에 트랜잭션을 보내는 user 또한 허가받은 사람만 가능하며, 그들의 실체는 X.509로 규정되어진다. 하지만 Qourum , Besu는 그냥 user 는 이더리움과 같은 공개키로 만들어지는 anonymous 이다. Genesis 파일상에서 만들어지는 어카운트들을 이용해서 주로 사용하며, ACL은 스마트컨트랙트에서 관리한다. 

체크2)
Hyperledger Fabric에서는 ZKP 를 Identity Mixer 모듈을 가져다가 사용한다. 패브릭에서 트랜잭션을 보낼 때 보통 X.509 인증서를 포함해서 보내게 되는데, 여기에는 User의 정보가 모두 노출되어 있다. 선택적으로 노출시키고 트랜잭션 마다의 연계성을 끊기 위해 영지식증명이 사용된다. 결론은 패브릭은 용도에 따라서 선택 할 수 있다. 노출 할 건지, 숨길 건지

체크3)
Order → Execute / Validate 모델과 달리 하이퍼레저 패브릭의 EOV(Execute → Order → Validate) 모델은 이는 체인코드 실행시 발생 할 수 있는 다양한 악의적 혹은 비결정적 문제에 대해 Client 와 Validate 시점에 Endorsement Policy에 의해 걸러지게 해 최종적으로 동일한 상태를 보장 할 수 있게 도와준다. 비결정적 문제에 대해 어떻게 제한을 가 할 지는 네트워크 구성원 끼리의 거버넌스에 따라 달라 질 것이다.

3-1) Fabric에서 Endorser로 부터 반환된 R/W Set이 악의적인 결과인지 비결정적인 문제인지는 클라이언트에서 판단 할 수 없다. differentiation 을 auto resolve 할 수 있는 방법도 없다. Avis에서는 Proxy에서 과반이 아닌 Peer에 emergency recovery call 을 보내는 설계를 고려하고 있으나 더 생각을 해 봐야 한다.

3-2) Corda 는 특이하게 피어들끼리 트랜잭션을 먼저 검증한 후에, Notary를 통해 이중지불을 확인 한 후에 최종적으로 양쪽에 커밋된다. (모든 피어들이 커밋정보를 가지고 있는 것과 다르게 관심을 공유하는 피어들 끼리만 공유한다) 

체크4)
hyperledger faric은 비결정적


체크5)

ING에서는 영지식증명을 Corda에 추가해서 프라이버시를 추가했다. https://www.coindeskkorea.com/59656/

체크6)
Hyperledger Besu는 Hyperledger 재단의 첫번째 퍼브릭(가능)제품으로써, 합의 알고리즘에 따라서 캐릭터가 달라질 수 있다. 즉 PoA계열 알고리즘을 통해서 엔터프라이즈향에 적합해 질 수도 있다. IBFT2.0 (이스탄불 BFT 2.0)은 GoQuorum의 IBFT1.0을 개선하여 적용하였다. 

체크7)
성능에 관해서 제일 궁금 하실 텐데, 사실 패브릭 제외하고는 다양한 설정등에 기반한 성능지표에 대한 자료가 너무 부족하다.

체크8)
Besu의 경우 그룹별 프라이빗 원장 공유로 Orion이라는 기술을 이용한다. 패브릭의 채널과 비슷하다고 보면 된다. 사실 Orion은 Qourum에도 적용 될 수 있긴 하다. 

체크9) Qourum의 경우 프라이빗 트랜잭션으로 Tessera 를 이용한다. Orion과 Tessera의 차이점은 따로 블로깅 하려한다. 최근에 Besu도 Tessera를 지원하게 됬다. 


최근 추가 내용 

Hyperledger besu )
- EIP-1559 적용 (가스비 산정 변경, EIP-1559를 포함한 런던하드포크는 8월적용됨)
- EthStat 적용

GoQuorum )
- QBFT 추가
- EIP1559랑 무관. 가스비는 여전히 무의미(0) 하며 가스개념은 존재

Hyperledger Besu ans GoQuorum 상호운용성)
- 동일한 컨센서스하 (QBFT) 에서 상호운용 가능 개선
- Tessera 를 활용한 Privacy 기능이 이제 양쪽 모두에서 가능

툴 개선)
- Web3js-Quorum 새로운(기능보완) web3js 라이브러리로 ConsenSys Quorum node를 좀 더 잘 사용 할 수 있게 한다.







페이스북 :  엔터프라이즈 블록체인 그룹 


Hyperledger Indy에 대해서 정리해봤습니다. Indy는 변화,발전되고 있으며, 인사이드에 대한 정밀한 조사,검증을 하진 않았기 때문에 참고용으로만 읽어 주십시요. 4년전 처음 이글을 적을 때에는 Indy-SDK가 모든 것(블록체인과 인터페이스, DID,VC를 다루는 공통 함수들, 지갑역할, P2P역할, 익명성 역할) 을 다 담고 있었으나 2023년 3월 현재 Indy-SDK는 다양한 모듈별로 나누어진 버전들이 있습니다. (Aries, Indy-vdr,AnonCreds 등) 

개요

Hyperledger Fabric과 Ethereum의 경우 Smart Contract/ChainCode 를 통해서 DID/SSI를 (저장역할을) 실현 할 수 있는 범용 플랫폼인 반면에 Indy는 오직 DID를 구축하고자 하는 상황에 맞춤으로 만들어진 public(사용자) - permissioned (네트워크) 블록체인 플랫폼이며 다음과 같은 특징이 있습니다.

@ Sovrin Foundation (개발조직: Evernym) 에서 제공된 코드 기반의 프로젝트 
@ 사용자는 Public 이고 (아무나 사용가능)
@ 노드 관리는 Permissioned (선출된 대표노드: 일명 Steward가 Validation / Write 역할을 함)
@ ZKP에 기반한 비 노출적 신원 증명 암호학 처리
@ ZKP에 기반한 비 연결적 Identity 
@ 자체적인 합의 시스템이 있다-> RBFT  (PBFT에서 View Change 부분을 개선한 버전) 
@ 자신의 지갑에 개인정보 보관 및 관리 (지갑의 개념이 이더리움,비트코인의 그것보다 넓다. 즉 키 이외의 것도 저장) 
@ 자체 장부를 가지고 있으며, 신뢰성있게 선출된 분산 장부에 Public 정보들을 저장 / 읽기 한다.  
@ 보통 Agent라고 부르는 연관 End-Point 간에 암호화 된 연결 후 필요 정보 요청/검증 프로세스 
@ 스마트 컨트랙트 기능은 없다. 

Indy의 Credential / ZKP기반은 Fabric의 Identity Mixer와 같으며  Camenisch-Lysyanskaya (CL) signature scheme or BBS+ 으로 어떤 속성에 대해서 올바른 서명을 알고있다는 것을 실제 서명 자체를 노출하지 않고도 증명 할 수 있는 방식) Indy의 암호학적 근거에 대해서 더 자세하게 이해 하려면 https://www.evernym.com/white-papers/ : Evernym 백서인  핵심적인 레퍼런스를 읽어야 합니다.

네트워크 구성

Validate Node 
validator 노드는 RBFT구현인 Plenum 프로토콜에 의해 작동하며 주로 장부에 기록이 이루어 집니다.

Observer Node 
원장의 읽기 전용 사본이며 아래 3가지 역할을 합니다.

Read requests:  Validate Node의 성능에 영향을 주지 않고 ID 레코드에 대한 수요가 확장될 수 있도록 함.
Hot standbys: 기존 Validate Node에서 기술적 문제가 발생할 경우 active Validate Node로 서비스 전환될 수 있음.
Push subscriptions: 이벤트 알림을 배포하는 수단을 제공함.

Agent 
에이전트는 P2P 메시징 엔드포인트를 제공하여 일반적으로 자체 메시징 엔드포인트를 제공하지 않는 인디 클라이언트의 통신을 용이하게 합니다. Sovrin 에이전트는 다양한 장치에서 작동하는 여러 Sovrin 클라이언트 간에 메시지와 상태를 조정하며  Agent 는 Indy 키체인들의 암호화된 백업을 유지할 수 있고, ID 소유자를 위해 데이터를 단순하게 저장하고 공유할 수 있습니다. Indy에서 이 부분은 Hyperledger aries로 이전되었다.

App (Client)
신원 소유자(백서상 Identity owner 에서 Identity holder로 변경됨)들은 그들의 신원 정보를 Indy 클라이언트를 통해 통제하고 관리하는데, Client의 가장 중요한 기능은 Owner의 키 체인을 관리하고 보호하는 것으로 볼 수 있습니다. 
쉡게 풀어 무슨얘기냐하면 Indy sdk 클라이언트에 지갑기능이 있고, 그 지갑에 DID관련 키가 저장되어있다는 말

DIDs 와 Verifiable Credential

DID

사용자는 자신의 ID에 대해 기억할만한 이름을 만들어서 원장에 DID 형식으로 변환하여 저장합니다. (당연히 개인키는 자신의 지갑에 분리되어 저장됨) DID는 탈중앙형 식별자로, pure DID는 암호학적 속성을 가지고 있지 않으며 version 4 UUID를 사용하여 유니크하며 원장에 저장되고 원장에서 읽을 수 있습니다. 

각 DID는 주어진 네트워크에 특정한 method 사양과 연관되어 있으며, DID method 는 해당 네트워크에서 DID가 등록, 확인, 업데이트 및 해지되는 방법에 대한 규칙을 지정합니다.

DID Document

DID Docuement에는 주로 해당 DID를 어떻게 검증 할 수 있는지에 대해서 나와있다. DID가 진짜 그 사람의 소유인지를 확인하려면 DID의 쌍인 Private key를 가지고있는지 확인하면 된다. Document에 있는 DID 소유자의 끝점을 통해 테스팅 할 수 있다. 또한 DID의 소유를 확인하기 위해서는 단일소유주 뿐만아니라 다양한 방식으로 테스트 할 수 있는데 예를들어 소유자가 회사의 구성원이라면 회사가 대신해서 검증 해 줄 수 도 있을 것이다. 

Verifiable Credential

정체성과 관련된 단일 속성을 Claim이라고 하는데 Claim은 한 명의 신분 소유자(사람 또는 조직)가 자신이나 다른 신분 소유자에 대해 제공하는 속성 정보를 말합니다. 예를들어 Claim은 주민등록증 상의 나이를 나타낸다고 생각하면 됩니다.  혹시 Credential하고 헤깔릴수도 있을텐데, 2018년에 Evernym 백서상에서 claim들의 묶음인 claims라는 용어를 credential로 바꿨다고 합니다. 참고로 주민등록상(혹은 운전면허증) 상의 모든 정보를 Verifiable Credential 이라고 하고, 해당 정보 중에 편의점에서 필요로 하는 최소한의 노출 정보(나이겠죠?)를 Verifiable Presentation 이라고 합니다.

Claim(단일속성) -> Credential(단일속성들의 전체합) -> Presentation (노출시키고자 하는 속성만의 합) 

DID 말고 CID는?

CIDs는 Cryptographic IDentifiers의 약자로써, pure DID가 단순UUID인것 비해서 공개키,공개키의 해시와 같은 암호학적 특징을 가지고 있으며 제안된 cid-1 스키마는 아래와 같습니다.
• The starting value is a 256 bit Ed25519 public key.
• This value is then base58Check encoding to produce a 44 character string

Example: cid-1:MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCABMC

먼가 복잡해 보인다면 하나만 기억하세요. DID나 CID나 사용자가 스스로 만든다는 것이며 중앙기관에서 누군가가 만들어 주는 게 아닙니다. 여담이지만 Hyperledger Indy는 SSI는 잘 지켜지지만, DID로써는 조금 약한게 사실입니다. 중앙화는 탈피 했지만 완벽한 분산(탈중앙)은 아니라는 말이데, 작동 가능한 정도의 합리적인 탈중앙성을 보유하고 있다라고 말하고 싶습니다. 

Interoperability of Digital Certificates

디지털 인증서는 상호운용성을 보장하는 필수적인 형식인데, X.509는 식별자와 필요한 메타데이터로 암호키를 바인딩하여 공개키 인증서를 정의하는 표준입니다. 이  X.509 인증서는 일반적으로 계층적 PKI 모델에서 작동하는 CA에 의해 배포되는 반면 DID와 DDO는 디지털 아이덴티티가 피어로서 상호 운용될 수 있도록 합니다. 검증 가능한 Credential을 상호 작용, 연결 및 공유할 때 Peers는 필요에 따라 복수의 겹치는 "신뢰의 거미줄"을 형성 하는데 X.509 인증서를 생성하는 데 DID 및 DDO 핵심 자료와 메타데이터를 사용할 수 있으며, X.509 인증서는 DID/DDO 모델과 함께 검증 가능한 Credential으로 사용할 수 있습니다. 이런 식으로 두 모델 모두 서로와 상호작용 될 수 있습니다. (사실 이 부분에 대한 정확한 작동 방식은 아직 분명하진 않습니다. 추후에 보충 설명하겠습니다) 

DIDComm

에이전트간의 통신인 DIDComm 및 구현체인 Aries에 대해선 나중에 기회되면 서술합니다. 
https://identity.foundation/didcomm-messaging/spec/


스토리 라인

대략적인 스토리 라인을 살펴 보겠습니다. (이 스토리라인은 Indy와 Aries을 이용해서 구현 가능합니다.) 

Actor

공통) KeyPair 생성 -> Ledger 에 DID 및 DID Document 저장 , 지갑에 Secret key 저장. 

@Government :
기본 schema 를 설정하는 역할. (schema란 졸업증명서라든지 재직증명서등의 기본구성요소를 정의해 놓은 것이다.)
@Alice:

 Faber College에 성적표 요청 
 Acme Corp에 입사신청 (prover 및 credential holder 롤) 
@Faber College :
 Alice에게 성적표 발급(credential issuer 롤)
@Acme Corp :
 지원 서류 중 하나로 지원자에게 학교 성적표 요구 (credential verifer 롤) 
 Alice에게 재직 증명서 발급 (credential issuer 롤)

Step 1. Steward의 Trust Anchor 생성

Steward 는 분산되어 DID 관련 데이터를 블록체인에 저장/읽기 한다. Steward는 참여하는 모든 actor (Trust Anchor) 들을 생성할 수 있고 각 actor마다 적당한 역할을 부여한다. 

Step 2. 각자의 DID를 Ledger에 생성

아래 글은 백서(The Technical Foundations of Sovrin) 중 First-Time Provisioning에 나오는데, 새로운 Sovrin ID의 최초 설정 (Provisioning)을 위한 기본 단계는 다음과 같다. (즉 엘리스가 자신의 ID를 만들고 DID를 Ledger에 등록하는 상황)

ID Owner는 먼저 Aries같은 Sovrin 클라이언트(브라우저/스마트폰 혹은 클라우드에 연계된) 를 사용 하여 Trust anchor의 웹서비스나 웹싸이트에 연결 한다. (이때 DID 말고 해당 웹싸이트에서 요구하는 개별적 인증을 사용함) 

1. Sovrin 클라이언트(SDK) -> Trust anchor 로 연결
2. Trust anchor -> Sovrin 클라이언트로 챌린지 토큰을 리턴함.
3. Sovrin 클라이언트는 KeyPair 생성 
  3-1. Sovrin 클라이언트는 Owner의 Sovrin Keychain에 추가 
  3-2. KeyPair 중 Public(verification) key는 Sovrin identifier를 생성하기 위해 사용됨. 
  3-3. KeyPair 중 Private (signing) key는 챌린지 토큰을 서명하는데 사용됨.

4. Sovrin 클라이언트 -> Trust Anchor로 서명된 챌린지 토큰 보냄. 
5. Trust Anchor 는 챌린지 토큰의 서명을 확인하여 새 키쌍을 인증한 다음 새로운 Sovrin Identifier를 Sovrin Ledger에 등록하는 프로세스 진행 
6. Trust Anchor -> Sovrin 클라이언트로 등록에 대한 receipt 메세지와 자신의 private key 서명을 리턴함. 
7. Sovrin 클라이언트는 Sovrin 원장을 확인하여 Trust Anchor의 서명을 최종 확인. 

먼가 복잡한데 Indy SDK에선 단순히 이렇게 한다. (지갑이 중앙화 되었다) 

 alice= { 이름, 지갑id, 지갑 비번, Indy풀) // 지갑 기본 정보 기입하고  (1) 
 create_wallet(alice)  // 기본 정보를 통해 지갑을 만들고 (2) 
 (alice['did'], alice['key']) = await did.create_and_store_my_did(alice['wallet'], "{}")  // did과 부속물을 만들어서 지갑에 저장하고 did키와 verifying key를 리턴해 준다. 이 verifying key를 서버 혹은 개인이 선택 보관 할 수 있다. 

매우 간단하다. 

 DID가 실제 엘리스 혹은 지영이인지는 어떻게 알 수 있을까??
당연히 알 수 없다. DID는 그저 UUID일 뿐이고, DID가 링크하는 DID Document는 public key와 엔드포인트등 문자열을 가지고 있을 뿐.. 설사 거기에 이름을 적었더라도 그게 진짜인지 알 수 없다. 

실제 지영이,엘리스를 인증하는건 그 DID와 매칭되는 Credential을 통해 한다.  이 Credential을 누가 해줬냐에 따라서 신뢰의 강도가 달라지며, 국가기관이 동사무소에서 직접 얼굴보고 확인 해줘서 Credential을 하면 가장 확실하며(국기기관의 Credential에는 그 DID와 연결되는 나이,이름,주소,민증번호등이 있을 거고)  그것이 개인의 가장 Root Credential이 되면 좋을 것이다. 그 이하 신뢰의 강도를 가진 Credential이라면 그냥 특정기관,은행단위일 것이고....

Step 3. [Credential Issuer] Credential Definition 생성

Alice에게 credential을 발급해주기 위해서 필요한 양식 (schema 와 credential definition)들을 만들어 ledger에 저장한다.

즉, Goverment는 기본 스키마를 ledger에 저장해두며 Faber college는 Alice에게 성적표 발급에 필요한 Transcript Credential Definition을 만들어서 ledger에 저장하고, Acme Corp는 재직 증명서를 발급하는데 필요한 Job-Certificate Credential Definition을 만들어서 ledger에 저장한다.

Credential Definition은 schema에 기반하여 만들어지며, 필요한 정보들을 추가적으로 넣을 수 있다.

Step 4. [Credential Issuer] Credential 발급

앨리스는 credential을 faber college로부터 발급받기 위하여 faber college와 secure channel을 생성한다. 생성된 안전한 channel을 통하여 faber college는 Credential Definition에 해당하는 앨리스의 정보를 입력하여 앨리스에게 전송한다.

이 예제에서는 Faber college는 Alice에 대한

@이름
@학위
@졸업 여부
@연도와 학점
@SSN

에 대한 정보를 발급하여 Alice에게 (서명과 함께) 전달한다.  발급받은 인증서는 엘리스의 지갑에 저장된다. 

Step 5. [Credential Verifier] Credential 요청 및 검증

Acme Corp는 앨리스에게 학교 성적과 관련된 정보들을 요청하기 위하여 앨리스와 secure channel을 생성하고, 회사 지원을 위해서 학위, 현재 상태, SSN에 대한 정보가 필요하다고 Alice에게 요청을 한다. 앨리스는 Faber college로부터 받은 정보들을 기반으로 Acme Corp가 요구하는 정보들을 전달하고, 전달한 정보가 Faber college가 발급해준 정보가 맞다는 사실에 대한 증명을 추가로 생성하여 Acme Corp에게 전달한다.Acme Corp는 Alice가 전송해준 증명을 통하여 전송받은 정보가 Faber College로부터 발급된 정보라는 것을 확인한다.


Alice's Identity 는 ? 

그럼 이 네트워크에서 앨리스는 어떻게 식별되었을까? 앨리스는 각각의 조직과 의사소통을 할 때 마다 다른 DID를 이용한다. 스토리 라인에서 앨리스와 조직 사이에 먼저 보안 연결이 성립 해야 한다고 했는데, 이 보안 연결에 필요한 것이  pairwise-unique DID 이며, pairwise-unique DID는 오직 해당 조직과의 연결에만 사용 된다.

만약 현재 앨리스의 지갑을 열어서 그녀가 얼마나 많은 DID를 가지고 있는지를 확인 하면, 그녀가 이전에 소통했던 각 조직 (Faber College, Acme Corp, Thrift Bank)마다 한 개씩, 즉 3개의 DID가 있다는 것을 확인 할 수 있으며, 위에 말한바와 같이 서로 다른 DID이며, 이 세 개의 DID는 모두 대응되는 verkey와 함께 원장에 기록된다. 그 밖에 원장에는 앨리스에 관한 다른 어떤 것도 찾을 수 없다. (예를들어 나이,학교,회사정보 등등)
다른 어떤 것~! 즉 필요로 하는 속성을 얻기 위해서는 엘리스와 직접 보안 통신하여 요청하고, 확인 해야 한다. 

결국 블록체인(Ledger)에 저장되는 건 무엇인가? 

-Public DIDs and associated DID documents with verification keys and endpoints.
-Schemas and credential definitions
-Revocation registries
-Agent authorisation policies


공개 해야하며 공개되도 괜찮은 것이다. 예를들면 verifier는 issuer의 DID,Public Key를 장부에서 찾아야한다. (은행은 자신의 Public DID를 은행의 홈페이지에 QR코드등을 통해서 게시해 둘 수 있다.) 서로의 DID를 검증하는 것등의 안전한 P2P통신을 하기 위한 정보들이 있다. 그리고 신원서가 유효한지도 확인 할 수 있는 기록들이 저장된다. 예를들어 재직증명서를 발급받았더라도 회사를 떠나게 되면 무효화 되야하니깐~

결국 블록체인에 저장 안되는 건 무엇인가? 

-Signing key 
-Private credentials (Verifiable Proofs )
-Consent receipts or data exchange records


이런 정보는 Ledger에 존재하여 아무나 찾아 볼 수 있게 하면 안되며,  Alice-to-Faber, Alice-to-Acme, and Alice-to-Thrift 등과 같은 보안연결 하에 Peer to Peer로 제공되야 한다. 


부록)

이 글을 처음 쓸 때만 하더라도 Indy만으로 모든게 다 되었지만 현재 P2P관련된 부분에서 Aries로 분리되었다.
Hyperledger Aries를 살펴본다. 

1. Hyperledger Aries 기능 

 Tool kit designed for creating, transmitting and storing verifiable digital credentials
  Anchor to blockchain
  Blockchain agnostic
●  Key management
●  DIDs
●  Messaging

2. 2023년 1월 31일 현재, 지원되는 Agents는 아래와 같다

  • Aries Cloud Agent - Python (ACA-Py) is suitable for all non-mobile agent applications and has production deployments. ACA-Py and a controller run together, communicating across an HTTP interface. Your controller can be written in any language and ACA-Py embeds the Indy-SDK.
  • Aries Framework - .NET can be used for building mobile (via Xamarin) and server-side agents and has production deployments. The controller for an aries-framework-dotnet app can be written in any language supporting embedding the framework as a library in the controller. The framework embeds the Indy-SDK.
  • Aries Static Agent - Python is a configurable agent that does not use persistent storage.

There are several other frameworks that are currently under active development, including:

  • Aries Framework - Go is a pure golang framework that provides a similar architecture to ACA-Py, exposing an HTTP interface for its companion controller. The framework does not currently embed the Indy SDK and work on supporting a golang-based verifiable credentials implementation is in progress
  • aries-sdk-ruby
  • aries-framework-javascript

아직도 Kotlin/Swift 구현이 없군요.

3. 주요 특성 
-
It acts as a fiduciary on behalf of a single identity owner (수탁자 역할을 한다
- It holds cryptographic keys that uniquely embody its delegated authorization. (개인키를 관리한다
- Aries agent will act your behalf to issue create connections, issue credentials, send messages (커넥션,발급,검증기능
- a mobile agent and a cloud agent. These agents are grouped based on their "location", e.g. a mobile wallet or server. Some other categories are a static, thin, thick and rich Aries agents. Aries JavaScript ecosystem allows you to create a mobile agent and a cloud agent. (Aries 자바스크립트 에이전트로는 중앙화된 클라우드형과 독립적인 P2P형 모두 만들 수 있다)

4. Build Your Identity Solution Using Hyperledger Aries



레퍼런스) 
https://www.evernym.com/white-papers/ : Evernym 백서
https://eprint.iacr.org/2016/663.pdf : BBS+ Signature 논문 
https://try.connect.me/
https://medium.com/@kctheservant/exploring-hyperledger-indy-through-indy-dev-example-10075d2547ae
https://www.ernesto.net/hyperledger-indy-architecture/
https://wso2.com/blog/research/the-rise-of-self-sovereign-identity-hyperledger-indy

FastFabric: Scaling Hyperledger Fabric to 20,000 Transactions per Second

패브릭 기술에 관심있는 사람이라면 한번은 보지 않았을 까 하는 논문인데..

과연 어떤식으로 커스터마이징을 하면 20,000 TPS를 달성 할 수 있을까? 이 논문에서는 Hyperledger Fabric 1.2 기반 (1.4에도 적용 가능)으로 아키텍쳐를 변경하여 성능을 3,000 TPS에서 20,000 TPS로 높였다고 하는데 과연 어떤 부분을 고쳐서 일까? 말이 되는 소릴 하는 걸까? 이것에 관해 각각의 토픽에 대해  배경지식/논문의 해결방식/개인적인소견(문제점)으로 정리하고자 한다.

1. Orderer - Seperate transaction header from payload

배경지식:  orderer 는 client로 부터  트랜잭션을 받는데, 트랜잭션 내부에는 Transaction ID 와 함께 endorser 들의 서명과 RWSet 등을 포함한 작지 않은 Payload가 있다. 이런 데이터들을 받아서 각 오더러는 Kafka에 전달하여 정렬을 하게 되는데, 정렬된 트랜잭션의 뭉치를 모아서 하나의 블록으로 생성하는 구조이다. 

 해결: Kafka에 정렬을 위해 보내는 데이터의 크기를 줄인다. 즉 모든 트랜잭션 데이터를 전송하는게 아니라, 트랜잭션을 대표하는 ID만 보내서 정렬 시킨 후에, orderer의 로컬 메모리에 저장되있던 트랜잭션 데이터를 정렬된 ID에 맞춰서 가지고 와서 블록을 생성한다. Kafka의 부담을 줄인다는 것이다. 

 문제점: Orderer의 경우 SPOF 와 부하분산을 위해서 여러개가 존재 한다. 클라이언트는 여러개의 Orderer 중 하나를 선택해서 트랜잭션을 보낼 수 있으며, Orderer는 받은 트랜잭션을 역시 분산된 zookeeper-Kafka 클러스터의 broker 로 보내게 된다. 여러 Orderer 는 모두 다른 데이터를 가지고 있으며, Kafka는 이 데이터들을 모아서 순서를 만드는데, Orderer 중 하나는 Kafka 로 부터 consuming 하여 committer에게 전달 할 블록을 만들게 된다. 여기서 만약 Kafka 로 부터 Transaction ID 만 받는다면, 원래 Payload 는 어디서 가져와야 할까? 원래 자신이 받은 Payload야 자신의 메모리에 관리 할 수 있겠지만, 다른 Orderer가 받은 것은?? 결국 Orderer 간에 통신 하는 부분이 추가 되야 하며, Kafka가 정렬하는 중간에 Orderer가 죽는다면 SPOF가 발생되고 만다. 모든 Orderer가 공통으로 관리하는 스토리지를 따로 둔다고 하면? 그 자체로 SPOF 이다. 

2. Orderer - Message pipelining

배경지식:  orderer 는 client로 부터 트랜잭션을 받는데, 트랜잭션에 대한 다양한 validation 검사(채널검증,클라이언트 서명검증등) 를 진행하고, Kafka로 넣어준다. 이 검증이 끝난 후에야 다른 트랜잭션에 대한 처리를 한다.

해결:  받은 트랜잭션을 검증 작업을 위한 쓰레드풀에 던져서 동시성으로 처리. 먼저 검증을 끝낸 트랜잭션을 consumer에서 받아서 Kafka에 넣어준다. 전형적인 동시성 처리 파이프라이닝. 

의견:  OK  ( 근데 동시성,멀티쓰레딩이 항상 옳은것은 아니다. [블록체인] TPS 그리고 Disruptor 패턴

3. Peer - Replacing the world state database with a hash table

배경지식Orderer로 부터 받은 블록을 committer는 여러 단계의 검증 행위(1. 패킷정합성 검사 2. client 와 endorser 의 서명 검사 3. rwset 검사)를 수행한 후 최종적으로 Ledger (블록체인, StateDB)에 커밋하게 된다. 이때 rwset 검증을 위한 levelDB 의 i/o 에 많은 부하가 걸리는데...

해결:  
Fabric의 key-value 저장소를 가벼운 in-memory 데이터 구조로 변경. Fabric의 데이터 관리 계층을 가벼운 hash table로 재설계. stateDB 에 저장되는 양은 블록데이터에 비하면 아주 작다..라고 주장... 하지만..

문제점
양에 대해서는 절대 작지 않다. value에 무엇이 저장 될 지 알 수 없으며, 서버가 갑자기 다운이라도 된다면 모두 소실되는데, 그때마다 다른 곳에서 다시 block sync를 받아야 하며 그 부하가 대단하다. 참고로 leveldb 자체도  write에 최적화된 매우 빠른 db이며 가능한 in-memory에 저장을 많이 해두고 있다가, 디스크로 쓰는 구조이다. 

4. Peer- Store blocks using a peer cluster

배경지식블록은 최종적으로 Ledger로 남는데, Ledger 는 최종 상태만 보관하는 StateDB 와 모든 데이터를 append only 로 붙히는 블록체인으로 이루어 진다..(패브릭에서 statedb는 leveldb or couchdb를 이용하고 블록체인은 그냥 file에 쓴다)

해결
Peer가 단독적으로 관리하지 말고 Hadoop MapReduce 나 Spark 를 사용하자. 

문제점
kafka-zookeeper도 관리문제가 있는데, 또 외부시스템을 사용하자고? 게다가 현재 블록데이터를 그냥 bulk file write 하는것에 비해 훨씬 느려지는 것은 당연하다. 문제는 statedb의 디스크 i/o지 저런게 아니다. 

5. Peer - Separate commitment and endorsement 

배경지식Fabric에서 Peer 는 commtment역할을 무조건 하고, 옵션에 따라서 endorsement역할도 한다. 이 두가지 모두 많은 부하를 갖게 되는데, 하나의 서버에서 돌리면 많은 수의 CPU를 동시에 사용하게 되어, 컨텍스트 스위칭 비효율을 낳게 되고 마는데..

해결:  
committer와 endorser를 다른 하드웨어로 분리함.

의견
성능을 위해서라면 당연히 해야 하는 것이다. 네트워킹파워가 엄청난 이 시대에 둘이 공통으로 접근해야 하는 stateDB는 공통 접근 할 수 있는 곳에 따로 놓아도 된다. 컨텍스트 스위칭 문제가 생각보다 훨씬 병목이 된다. 참고로 블록체인 데이터는 committer만 사용한다. (그냥 append only ) 유일한 문제점은 관리자 입장에서 관리 대상이 몇개 더 늘어난 것일 뿐이니..(msp등) 성능이 핵심이라면 트레이드 오프가 당연. 

6. Peer - Parallelize validation 

배경지식Orderer로 부터 받은 블록을 committer는 여러 단계의 검증 행위 (1. 패킷정합성 검사 2. client 와 endorser 의 서명 검사 3. rwset 검사)를 수행 한다고 위에 언급했다. 하나의 블록 안에는 수많은 트랜잭션이 있고, 그 트랜잭션 안에는 역시 수 많은 서명,RWSet이 있을 것이다. 이것을 CPU 하나로 처리 한다면?? 으악...

해결:  
병렬적으로 처리 할 수 있는 것은 병렬로 처리하자.

문제점
조심 해야 하는 요소들이 있다. leveldb의 동작특성을 이해해야 하며 (batch write 같은) Reply attact, Double spending 의 위험성에 노출 될 수 도 있다. 너무 많은 동시 처리는 컨텍스트 스위칭을 일으켜서 오히려 병목이 될 수도 있다. CPU 말고 다른 장치를 사용 해서 서명검증등을 처리 하는 방안을 추가로 강구 해야 할 것이다.    

7. Peer - Cache unmarshaled blocks

배경지식대부분의 분산 시스템에서 객체 이동은 빠질 수 없는 부분이다. 패브릭도 proposal request, proposal response, transaction, block progagation 등 수 많은 객체 이동(복사)가 네트워크를 통해 발생하는데, 이럴때 직렬화,역직렬화가 필수적이다. 근데 직렬화,역직렬화라는 것은 추상성이 높을 수록 복잡해 지게 마련인데, 추상성이 높으면 사용성은 높아진다. 즉 자바를 예로 들면 추상성이 높아서 사용하기 편한 반면, 직렬화,역직렬화에 들어가는 비용은 높아지게 된다. 따라서 자바표준직렬화를 속도가 필요한 부분에서는 사용하지 않으며, 커스터마이징 하게 마련이다. 반대로 C++를 사용하면 "손쉽게" 직렬화,역직렬화에 비용소모를 엄청 줄일 수 있다. 네트워크간의 직렬화 말고, 메모리 내부에서도 작업이 분리되 있으며, 데이터 이동(복사)가 반드시 필요하게 되는데, 이것도 가능한 deep copy를 줄이고, move로 처리해야 하는 부분이다. 논문에서 주목하는 부분은 후자(내부 프로세스에서의 객체 분해/조립 병목) 이다. 

해결:  
패브릭에서의 블록내부구조는 하나의 구조체로 이루어져 있는 것이 아니라, 구조체의 구조체의 구조체의... 이렇게 여러 레이어들의 합인데, 하위호환성 및 유연성을 반영한 설계이다. 역시 모든 것에는 트레이드 오프가 있는 법, 유연성이 증가한 만큼 사용시 부담이 생긴다. committer에서 validation 과정이 여러개라고 위에서 언급했는데 각각의 행위에는 블록구조를 분해/조립 (byte array <-> object)해서 필요한 것만 가져가서 사용하는데, 이럴 경우 분해,재조립에 부하가 간다. 따라서 새로 만들어진 객체(unmarchaled data)를 cyclic buffer 형태의 블록캐시를 만들어두고 재사용하여 복사(분해,조립) 과정을 줄이는 방식이다. 

의견
성능이 제1덕목이라면 유연성/추상화를 줄여야한다. 다만 해당 부분이 전체 시스템에서 주요 병목인가를 잘 살펴봐야 겠다.  raw data로 부터 생성된 객체가 다른 worker들로 이동 될 때 어떻게  부하를 줄이냐는 각 언어별로 달라질 수 있을 것이고, 해당 객체에 대한 재사용 기법 또한 선택의 가짓수가 많은 C++의 경우에서는 특히 깊이있게 고민해야하는 부분일 것이다. 사실 이런 기법은 문장(string building)에 대한 편집을 다룰때 개발 단어를 최대한 캐시해두고, new를 통한 메모리 할당의 감소를 줄여서 대폭적인 성능 향상을 이루는 기법과 일맥 상통하다.   

P.S
이런 커스터마이징 정도로는 하이퍼레저 패브릭이 애시당초 의도한 엔터프라이즈 환경의 일부 인원들만 접근해서 사용하는 환경에서는 의미를 가질 수 있으나, 대규모의 다양한 사용자가 접근 해서 수 많은 비지니스 로직(체인코드)가 만들어지는 환경으로의 범위를 넓히고자 하는 사람들에게는 논문에서 언급되지 않은 다른 병목들도 있기에 사용성에 문제가 발생 할 여지가 있다. 

 

 

페이스북 :  엔터프라이즈 블록체인 그룹 

 

이 글은  버전을 구분하지 않고 있으며 , 스스로가 공부하면서 메모식으로 두서 없이 정리/수정 하는 내용인지라 글 읽기가 힘들 수 있으며, 암호학 전문가가 아니기에 일부 오류룰 담고 있을 수 있음을 참고 하십시요.

이더리움을 위시한 퍼블릭 블록체인에서는 굳이 네트워크에 붙는 노드들에 대한 신뢰가 필요 없기 때문에, 이 글에서 설명 할 하이퍼레저 패브릭이나 코다에서 신뢰,허가 작업을 하기 위한 복잡한 CA 관련 기술이 필요 없습니다. 대신 이더리움은 아무나 참여하는 네트워크에 대한 신뢰를 다른 방식으로 추가 하기 위한 더 어려운 일에 도전하고 있는 상황입니다. 

이 글에서는 하이퍼레저 패브릭과 코다에서 네트워크에 참여하는 노드들의 신뢰,허가작업들이 어떤게 있는지 살펴보겠습니다. 실제 메뉴얼들은 이 글 보다 훨씬 방대한 내용을 담고 있으며, 특히 허가,보안,거버넌스 부분은 패브릭의 가장 어려운 내용이라 할 수 있겠습니다. 

1. CA (certificate authority)

인증 기관이라는 의미이다. 즉 내가 누구인지  혹은 이 웹싸이트가 누구인지 인증해 주는 기능을 하는 것을 말한다.예를들어 네이버에 접속한다고 치면, 사용자의 브라우저는 네이버 서버에 접속을 하게 될 것이다. 이때 중간에 무엇인가 접속 신호를 가로채서 이상한 서버로 접속 할 수도 있을텐데, 이때 브라우저는 자신이 접속한 서버가 네이버라는 것을 어떻게 알 수 있을까? 

답은 네이버는 자신이 네이버라는 이름이 적힌 종이(예를들어)를 브라우저 한테 보내준다. 그럼 "아~ 네이버가 맞네" 하고 받아드린다. 응?? 뭔가 어설프다. 그 종이가 진짜 맞는지를 확인(인증)해주는 무엇인가가 필요하지 않을까? 그때 CA가 필요해진다. 

여기서 공개키/비밀키에 대한 얘기를 먼저 해야겠다. 사실 이 글을 읽는 분들이라면 다 아는 것이라고 생각하지만 간단히 설명하자면, 누구든 자신의 공개키/비밀키 한쌍을 만들 수 있으며, 비밀키는 자신만 고히 간직하고, 공개키는 사람들에게 뿌린다. 이때 "안녕하세요" 라는 문서를 비밀키라는 것으로 변환시켜서 "114ae2" 라고 변경된다고 할 경우, "114ae2" 를 다시 "안녕하세요" 라고 변경하기 위해서는 공개키로 풀면된다. 이 얘기는 공개키로 풀어서 "안녕하세요" 가 나오지 않는다면 비밀키나 공개키가 잘못되었다는 것을 의미한다. 즉 엘리스가 밥에게 "사랑한다" 라고 편지를 보내며 자신의 비밀키로 변환시켜서 "224eaf3" 이 나왔다고하자. 엘리스는 "사랑한다" 라는 편지와 새로 생성된 "224eaf3" 를 중간대리자를 통해 밥에게 전달하면, 밥은 엘리스의 공개키로 "224eaf3" 를 풀었을때 "사랑한다" 가 나온다면, 아 진짜 엘리스가 보낸게 맞구나. 라고 인정할수있게 된다. 이는 부인방지가 될 수도 있는데, 엘리스 자신이 "사랑한다" 라고 보내놓고, "응 그거 내가 보낸거 아니야" 라고 부인할 수 없다는 뜻이다. 

이 공개키/비밀키는 위에 언급한 CA에서 적극적으로 사용되는데, CA의 공개키는 브라우저에 뿌려져서 누구나 가지고 있게 된다. CA의 비밀키로는 네이버가 적은 "내가 네이버야" 종이를 변환해서 "3232DASF3" 라고 변환시킨후에 이 둘을 브라우저에 보내면, 브라우저는 CA의 공개키로 "3232DASF3" 를 복구 할 때 "내가 네이버야" 라고 복구된다면 신뢰 할 수 있게 되는 것이다. 

끝!! ???

근데 여기서 딴지를 거는 센스있는 분들이 있을 수 있겠다. 그렇다.  CA의 공개키는 브라우저에 뿌려져서 누구나 가지고 있게 된다이게 문제인데. 그럼 그 CA라는 놈의 공개키는 어떻게 믿을 수 있냐? 라고 말 할 수 있는데, 그땐 그 CA의 상위 CA가 인증을 해 줄 것이다. ㅎㅎ 아래 이미지를 보자. 

제일 위의 Root CA 는 스스로 인증을 하며, 그 아래 CA들은 그 부모(상위) CA에 의해서 인증된다. 
대략 이런 메커니즘이 있다는 것을 이해하고 하이퍼레저와 CORDA의 CA에 대해 알아보자.
조금 다른 것은 위의 CA 설명에서는 네이버라는 서버에 대한 인증이었다. HTTPS 에셔 사용되는 인증은 이런 서버에 대한 것이고, 서버가 아닌 클라이언트 즉 모든 피어가 CA 에 의해서 인증 받아서 서로에 대한 신뢰를 구축 할 수도 있는데,  하이퍼레저와 CORDA 에서는 하나의 중앙 서버가 아니라, 모든 노드들이 자신들의 인증을 CA 를 통해서 받게 된다. 탈중앙화 아니던가!!! 

* 2017년에는 구글이 직접 Root CA 를 운영한다고 한다. 구글이라면 믿을 만 하지 ㅎㅎ 
* 하이퍼레저나 CORDA 에서는 자신의 인프라 안에서 Root CA 및 자식 CA 들이 구축된다. 즉 스스로 발급기관 역할도 한다는 것.

2.하이퍼레저 패브릭과 CA,MSP 

하이퍼레즈 패브릭에서 
CA(인증 기관)는 사용자 등록, 블록체인에서 호출된 트랜잭션 블록체인의 사용자 또는 구성요소 간의 TLS 보안 연결과 관련이 있다.

2-1. 네트워크 구성 및 Fabric-CA (ver1.0~)

 
위의 그림은 일반적인 하이퍼레저 패브릭의 네트워크 구조도 이다. 아래와 같은 특성이 있다.

 - 먼저 CA 와 Fabric-CA 는 다른 것이니 혼동하지 말자. CA 는 간단히 말해 어떤것에 대한 증명 해 줄 수 있는 문서 목록이며, MSP를 통해 기관으로의 실시간 오퍼레이션을 하며, Fabric-CA 는 CA 기능에 관한 여러가지 오퍼레이션을 하는 서비스이다. 예를들어 cryptogen 유틸을 통해 CA 들을 구성 할 수 있으며, Fabric CA Server 를 통해서도 구성 할 수 있다. 
 - 전체 네트워크에는 중간 중간 마다 Fabric-CA 서비스가 있을 수 있다. (하나만 있어도 된다) 
 - 전체 네트워크의 CA 들의 Root CA 도 있다. 
 - 보통 조직마다 하나의 중간 Root CA (intermediate CA) 를 만든다. 
 - Fabric-CA 는 고가용성을 위한 프록시가 front에 있는 클러스터로 구성하면 안정적이다.
 - Fabric CA에 접근해서 서비스를 받고 싶은 경우 Fabric-CA Client를 통하거나, Fabric SDK 를 통해서 이용 할 수 있다. 
 - Fabric-CA 는 주로 도커 이미지로 실행 되며, 설정파일을 통해 백엔드에 MySQL 같은 RDB 를 이용한다. 
 - Fabric CA 를 통해서는 아래와 같은 서비스를 제공 받을 수 있다.

  • 각 조직,서비스등에 대한 신원 등록. LDAP 인증으로의 접속 매개.
     전체네트워크 범위 msp
     채널 범위 msp
     조직 자체의 msp
     조직 관리자의 msp
     조직 유저의 msp
     조직의 peer 의 msp 
  • Enrollment 인증서 발급 (ECerts 로써 아래 따로 설명함) 
  • 인증서 갱신 및 폐지 
개인적으로 아직 정확하게 cryptogen 과 Fabric-CA 의 기능상(API 갯수 및 능력)  차이점을 확인하진 않고 있으며 다음에 정리 할 예정이다. 일반적으로는 cryptogen 은 거의 모든 기반 cryptographic material 만들 수 있고, (미리 만들어 두고) 반면 Fabric-CA 는 PEER, USER, APP 에 대한 신원등록은 할 수 있으나, Orderer 는 아닌 것으로 알고 있으며,  Fabric-CA 는 주로 User (admin이나 일반) 의 신원 등록 (X.509 certificates) 를 동적으로  생성/저장/갱신/폐기 하기 위해 사용하고 있는 것으로 생각한다. 따라서 cryptogen 으로 만들 수 있는 것은 미리 만들어두고, 그 후로 Fabric-CA 를 사용하는 패턴을 활용하면 될 거 같다. 참고로 Fabric-CA 에는 User의 개인키를 저장해 두고 있진 않다. 더 자세한것은 이 링크를 참고하시라. -> Fabric CA User's Guide 

                                                         (Fabric 1.0 Fabric-CA)

2-2.  CA 계층도  (ver 0.6) 

패브릭의 CA 구조는 위의 그림과 같은데, 하나의 Root CA 로부터 가지쳐서 내려오며 상세 설명은 아래와 같다.

 - Enrollment CA 는 새로운 user 를 네트워크에 등록하는데 사용되는 CA 이다. 
 - Tranaction CA 는 등록된 사용자가 트랜잭션을 요청하는것에 사용되는 CA 이다.
 - TLS CA 는 사용자들이 원격피어와 통신을 할 때 보안 채널로써 활용된다. HTTPS 또한 TLS를 사용한다.
 - ECerts 는 CA 가 각각의 멤버 컴포넌트(사용자,서버서비스)들에게 등록에 사용하라고 발행 인증서 자체이다.RA에서 만들어진 개인증명서를 통해 발행 
 - TCerts 는 CA 가 사용자가 트랜잭션 요청에 사용하라고 발행하는 인증서 자체이다. ECert 를 통해 발행

각각의 CA 를 통해 각각의 ECerts / TCerts 가 최종 생성된다. 참고로 TCerts 는 1.x부터는 컨셉에서 사라진것으로 알고 있다. 대신 3번에서 소개 하는 Identity Mixer 가 사용된다. 

2-3. 실제 네트워크의 허가/인증 관련 구성  (ver 1.0~)
first-network 예제의 cryptogen 유틸을 이용해서 생성된 디렉토리를 보면,

위 처럼 org1 이라는 조직에 대한 ROOT CA가 있으며, 즉 조직마다 CA가 생기며, 그 아래 peers, users 각각에 대한 MSP(와 조직 ROOT CA로 부터 생성된  CA) 가 존재하고 있음을 알 수 있다. 또한 각 폴더에 생긴 인증서파일인 .pem 을 열어보면

위처럼 org1 이라는 이름의 조직을 대표하는 CA가 있고,그것은 스스로 서명을 하는 Root CA로 작동하고 있으며, 그것을 이용하여 아래와 같이 peer0,Admin,orderer 각각의 인증서가 만들어진 모습을 볼 수 있다,

이런 인증서를 기반으로 Fabric CA 서버/클라이언트를 통해 각각의 ECerts / TCerts 가 최종 생성 될 것이다.
참고로 fabcar 예제의 enrollAdmiin.js 과 registerUser.js 를 실행시키면 프로젝트의 루트에 있는  hfc-key-store 디렉토리에 아래와 같이 admin과 User에 대한  eCert 와 키 쌍을 출력 한다. 

2-4.  Tranaction Certificates 요청 프로세스 ( ver 0.6 

트랜잭션시 사용되는 TCerts 인증서가 사용되는 과정에 대해 좀 더 디테일하게 살펴 볼 수 있는데,
자세한 설명은 이 링크를 참고 하시라~ https://rezamtfabric.readthedocs.io/en/stable/protocol-spec.html
이 부분은 (실험버전) 으로 지금(1.2버전)에서과 많이 다르지만, 설명이 너무 자세해서 읽어볼만 하다.


2-5. MSP (ver1.0~)

  (Fabric 1.0 MSP)

MSP (Membership Service Provider)는 이름 그대로 멤버쉽 서비스에 대한 아키텍처의 추상을 제공하는 목적의 컴포넌트이다. 인증서를 발급하거나 검증하고 사용자 및 서비스의  신원에 대한 작업과 관련된 일을 한다는 의미이다. 조직마다 보통 하나의 MSP가 있으며 MSP ID로 구분된다. 추가 정보로 MSP는 네트워크 범위에서 부터 로컬의 범위에도 존재 한다.

 

  •  전체네트워크 범위 msp
  •  채널 범위 msp
  •  조직 자체의 msp
  •  조직 관리자의 msp
  •  조직 유저의 msp
  •  조직의 peer 의 msp  

자 그럼 이것이 Fabric CA와는 무엇이 다른 것일까? 

fabric의 표준 심플인 
fabric-samples/first-network 에서는 cryptogen 유틸을 통해 MSP가 작동하기 위한 초기 정보들을 제공해 주고 있다. 아래 그림과 같이 조직마다 CA (Fabric CA 서비스가 아니다) 와 MSP 를 가지고 있는 모습이다. 조직마다 생성된 CA 와 MSP 는 전체 네트워크에 정보가 공유 되어 서로 검증하는데 사용 될 수 있다. 참고로 cyrptogen 을 이용하지 않고 fabric-CA 를 이용해서 생성 할 수도 있으며 (Orderer 제외),fabric-CA 는  fabric-ca-server init  명령어를 통해서 디폴트로 

fabric-ca-server-config.yaml

  환경파일을 생성하며 디비설정등을 할 수 있으며, cryptogen 유틸은 crypto config.yaml 설정파일을 이용한다. 

 

여기서 알 수 있는 것이 MSP,CA는 조직이 가지고 있어야 하지만, Fabric-CA 는 없어도 된다.(근데 실제 서비스에서는 없을 수가 없다)  cryptogen 을 통해서 조직이 사용할 각종 신원증명 매터리얼 들을 MSP의 초기화에 제공해 주면 되는 것이다. (실제 서비스에서는 이렇게 하긴 좀 머하지 않을까?) 반대로 cryptogen 없이 Fabric-CA 를 통해서 그런 신원증명 매터리얼을 만들 수도 있다.  즉 Fabric-CA 는 어떤 기본 정보를 제공해 주는 것이고, MSP 는 그 정보를 통해서 실제 어떤 오퍼레이션을 하는 것이라고 볼 수 있을 것이다. 

따라서 Fabric-CA 는 전체 네트워크에 하나만 있어도 되고, 여러개 있어도 되는 것이다. (글 초반에 말한것처럼 보통 한개가 HA로 구성되어 있을 것이다)

 

* 이 글을 쓸 현재는 Fabric CA 서버를 통해 생성된 사용자의 enrollment certificate (eCert)  fabcar 예제에서는 hfc-key-store 에 저장되는데, 이것들이 MSP와 어떤 연관관계를 가지고 고 있는지는 불명확하다. 실제 MSP 폴더를 열어보면 cryptogen 으로 부터 생성된 CA 정보들(조직의 root CA, PEER CA, USER CA, ORDERE CA,TLS CA)이 존재하는데 혹시나 MSP 가 enrollment certificate (eCert) 도 관여하는지는 잘 모르겠다. Fabric-CA 서버를 통해 만들어진 enrollment certificate (eCert)  가 사용시 이것을 검증하기 위한 CA로써의 역할을 MSP 가 하지 않을까 추측하고는 있다. 

 

체인코드에서의 MSP 사용 

하이퍼레저 패브릭의 체인코드적으로 MSP 를 말하자면 "어떤 조직에 속 할 경우" 에만 "어떤 체인코드의 메소드를 호출" 할 수 있는 권한을 부여하게 하는 역할을 한다. 실제 예를 생각해 보자, 개인들은 자신의 바이오인포매틱스 정보를 제공하고, 병원은 개인들의 의료정보를 저장하고, 연구조직에서는 해당 정보들을 가져다가 분석한다고 해보면, 각자의 그룹들이 나누어 질 것이며, 해당 그룹들은 체인코드(스마트 컨트랙트)의 모든 메소드를 호출 할 수는 없을 것이다. 즉 자신의 그룹과 관련된 메소드만 호출 할 수 있을 것인데, 그럼 개인들은 어떤 메소드만을 호출 할 수 있을까? 뭐 uploadPersonalData(....) 같은 것이겠지 않을까? 연구조직이라면 GetSomeKindOfPersonsBloodInfo(....) ? 

// 조직의 전용 mspID 와 certCN 을 통해서 확인하여, 호출 할 수 있는 조직을 경우에만 호출하게 제한한다. func authenticateExportingEntityOrg(mspID string, certCN string) bool {
return (mspID == "ExportingEntityOrgMSP") && (certCN == "ca.exportingentityorg.trade.com")
}

Hyperledger fabric 소스코드에서의 MSP 설명. 

 

Hyperledger Fabric 의 MSP api 란? 

하이퍼레저패브릭 네트워크에 참여하는 클라이언트나 피어들에게 (익명의) 증명서를 제공하기 위한 시스템의 추상 api 인터페이스이다.클라이언트는 이 증명서를 트랜잭션을 위해 사용하며, 피어들은 보증에 대한 트랜잭션 프로세싱의 결과를 인증하기 위해 사용한다. 이 인터페이스는 멤버쉽 서비스 컴포넌트 정의를 위해 사용되며, 이것을 통한 구현들은 코어 트랜잭션 프로세싱 컴포넌트의 수정없이 자연스겁게 플러그인 될 수 있을 것이다.이 소스파일은 MSP 인터페이스를 포함하고 있으며, MSPManager 는 MSPs 의 매니저를 정의하는 인터페이스이다. MSP를 호출하거나 라우팅하기 위한 매개객체로 행동한다. 


소스를 잠시 감상해보자. 

type MSPManager interface {
// IdentityDeserializer interface needs to be implemented by MSPManager
IdentityDeserializer
// Setup the MSP manager instance according to configuration information
Setup(msps []MSP) error
// GetMSPs Provides a list of Membership Service providers
GetMSPs() (map[string]MSP, error)
}

// MSP is the minimal Membership Service Provider Interface to be implemented
// to accommodate peer functionality
type MSP interface {
// IdentityDeserializer interface needs to be implemented by MSP
IdentityDeserializer
// Setup the MSP instance according to configuration information
Setup(config *msp.MSPConfig) error
// GetVersion returns the version of this MSP
GetVersion() MSPVersion
// GetType returns the provider type
GetType() ProviderType
// GetIdentifier returns the provider identifier
GetIdentifier() (string, error)
// GetSigningIdentity returns a signing identity corresponding to the provided identifier
GetSigningIdentity(identifier *IdentityIdentifier) (SigningIdentity, error)
// GetDefaultSigningIdentity returns the default signing identity
GetDefaultSigningIdentity() (SigningIdentity, error)
// GetTLSRootCerts returns the TLS root certificates for this MSP
GetTLSRootCerts() [][]byte
// GetTLSIntermediateCerts returns the TLS intermediate root certificates for this MSP
GetTLSIntermediateCerts() [][]byte
// Validate checks whether the supplied identity is valid
Validate(id Identity) error
// SatisfiesPrincipal checks whether the identity matches
// the description supplied in MSPPrincipal. The check may
// involve a byte-by-byte comparison (if the principal is
// a serialized identity) or may require MSP validation
SatisfiesPrincipal(id Identity, principal *msp.MSPPrincipal) error
}

MSP 정리 

- MSP 는 멤버쉽 오퍼레이션을 위한 추상층을 제공한다.
- MSP 추상층은 인증서 발생/검증 및 사용자인증에 관련된 암호적 메커니즘에 관련된 프로토콜이다. 
- 각 MSP 는 이름/ID 가 있어야 한다. 그 이름을 토대로 해당 멤버쉽 룰을 따르기 때문.
- 시스템 레벨에서는 채널생성, 채널레벨에서는 읽기/쓰기 컨트롤, 체인코드레벨에서는 함수호출제한 역할을 한다.
- 디폴트 MSP가 구현되어 있는데, RFC5280 에 따라서 다음 요소들이 포함한다.
ㅇ ROT 를 위한 
셀프 사인드 인증서 (X.509)
ㅇ intermediate CAs 의 X.509 인증서 리스트 (ROT를 바라봐야한다) 
ㅇ Organizational Units 리스트 
ㅇ ertificate revocation lists (CRLs) 리스트 
ㅇ 자가사인된  TLS ROT 
ㅇ intermediate TLS CAs 의 X.509 리스트 

MSP가 돌아가기 위한 기본 암호적 요소( signing keys and certificates) 들을 만들기 위해  “Cryptogen tool”  과 Fabric CA를 이용한다.
- MSP 를 셋업하기 위해 PEER & ORDERE 에는 6개의 서브폴더와 파일이 있어야 한다. (위에 폴더구성그림 참고)
- 노드의 설정파일을 셋업하는 동안 mspconfig폴더와 노드의 MSP의 MSP indentifier 패스를 설정해줘야한다.peer 를 위한 mspConfigPath 그리고 orderer 를 위한 LocalMSPDir 
- 채널에 대한 MSP 셋업은 오더러에 채널에 대한 제네시스 블록 (오더러를 시작하기 위한 네트워크 범위의 제네시스 블록과는 다르다)을 포함하는것으로 시작한다. 

3. Identity Mixer 

신원보호(unlinkability, minimal attribute disclosure) 측면에서 TCert 방식의 비효율적인 문제점을 개선하기 위해 나온 기술로써 영지식증명을 활용한다. (Camenisch-Lysyanskaya (CL) signature scheme or BBS+으로 어떤 속성에 대해서 올바른 서명을 알고있다는 것을 실제 서명 자체를 노출하지 않고도 증명 할 수 있는 방식으로 Flexible public keys, Flexible credentials 라는 특징을 가지고 있다) 

기존의 ECert 즉 User에 대한 신원증명서는 x.509 형식으로 되어있으며 해당 정보는 CA로 부터 발급받는데 세부정보가 모두 노출되어 있다. 따라서 해당 신원증명서를 첨부하여 트랜잭션을 호출 할 시, 자신의 정보를 모두 노출시키는 프라이버시 침해가 발생할 소지가 있다. 그렇다고 해서 신원증명서의 일부분을 제거하고 보낸다면, CA가 서명한 sign 코드는 무용지물이 될 것이고.. 이것을 보완하고자 등장한 것이 Identity Mixer 이다.

이 녀석은 위에서 말한 신원증명서의 일부 내용을 감춰서 보내도, 검증자 입장에서 CA가 인증해준 증명서라는 것을 똑같이 검증 할 수 있다. 이때 User의 public key 또한 호출 할 때 마다 변경이 가능하니,여러모로 프라이버시가 강화되는 것이다. 즉 소속을 숨겼는데, 소속을 Verifier가 알 수 있다는 의미의 영지식증명은 아니고, attribute가 바뀌었는데도 불구하고, CA가 동일하게 증명 할 수 있다는 의미의 영지식증명이다. 즉 너의 속성중무엇이 바뀌었던간에 너라는 존재가 맞다는 것에 대한 증명이다.

Fabtoken 에서 UTXO 개념으로 소유권을 관리하는데, 매번 바뀌어지는 public key를 사용하여 처리하지 않을 까 추측한다. 

ECert / TCert 처럼 X.509 나 Certificate 라고 표현하지 않고, Credentials 라 표현하고 있다. 즉 서로 다른 것이다.

X.509형식의 인증서를 매번 받는게 아니라, 한번 받은 Credential로 부터 새로운 Presention Policy를 적용한 것을 이용해 트랜잭션을 보내고 있다. Verifier 는 CA의 공개키로 모든 것에 대해 검증 가능하다.

  • Identity Mixer 크립토패키지는 발급자 키와 credentials 를 발급하고, presentation tokens를 생성하고 검증하며  key generation, signing, verification, zero-knowledge proofs 의 기능을 가지고 있다. (각 컴포넌트에서 가져다 사용하는 라이브러리라고 생각하면 된다. Fabric-CA처럼 단독실행서비스가 아니고, Fabric-CA에서도 가져다 쓰고, Java-SDK에서도 가져다 쓰는 라이브러리이다.)

  • 기존의 CA 서비스는 Identity Mixer 크립토 패키지를 이용하여 ECert credentials 를 발급한다.  

  • MSP는 Identity Mixer 크립토 패키지를 이용하여 트랜잭션에 대한 서명/검증을 수행한다. 

  • 각기 다른 언어로 만들어진 Client SDK를 위한 Identity Mixer 크립토 패키지가 만들어지고 있다.



레퍼런스:

https://hyperledger-fabric-ca.readthedocs.io/en/latest/users-guide.html
https://www.blogsaays.com/configure-msp-hyperledger-fabric-blockchain/
https://hyperledger-fabric.readthedocs.io/en/release-1.2/idemix.html
https://walkingtree.tech/x-509-identity-mixer-hyperledger-fabric/

 


Hyperledger fabric 에서 reply attact 을 막기위한 nonce는 랜덤으로 생성되는데, 해당 nonce 를 가지고 TXID 도 만듭니다. 따라서 nonce 는 트랜잭션마다 가지고 있게 되며, Ledger에 그대로 저장되어 - nonce를 검증하기 위해서는 해당 트랜잭션에 대해 Ledger에 이미 동일한 TxID를 가진 트랜잭션이 있는지에 대한 중복 검사를 통해 검증됩니다.

반면 이더리움이나 쿼롬등은 nonce는 Address마다 하나씩 가지고 있으며, 하나씩 증가합니다. 따라서 Address에 있는 nonce 값과 비교해서 검증을 하게 되죠.

결국 패브릭은 엄청난 공간의 낭비, 검증의 낭비를 초래하게 되는데요.( block index 를 통해 완화하긴 합니다. 근데 용량증가시와 MVCC 작업 까지 생각하면...) 왜 이렇게 해야 할 까요?

이것은 패브릭엔 Ledger에 Address 라는 상태 개념이 없으며, StateDB에는 체인코드와 연관된 key만 존재하기 때문입니다. 이더리움에서는 보낸 사람이 누구인지를 블록체인상에 존재하는 Address로 특정하지만, 패브릭에서는 그냥 CA 로부터 인증받은 user면 되며, 그 user는 체인코드를 호출하는데 있어서 인증서 검사 및 ACL에만 사용되지, 그 user의 정보가 Unique 한 key로 Ledger상에 존재하진 않기 때문입니다.

따라서 이런 낭비를 없애기 위해서는 해당 작업을 위한 별도의 서비스가 있으면 되겠지만, 그 서비스 자체에 대한 신뢰성이 블록체인(Ledger) 그 자체만 하지 않기 때문에 문제가 발생할 여지가 있습니다. 고민할 여지가 많은데 결국 근원을 바꾸는 수가 젤 좋겠죠. 

추가)
txid(nonce)에 대한 중복검사 자체를 굳이 해야 할 필요가 있을까요? multi version check로 퉁치면 안될까? 

+ Recent posts