Upgrade to Pro — share decks privately, control downloads, hide ads and more …

About blockchain consensus algorithm

Avatar for zoops zoops
November 20, 2018

About blockchain consensus algorithm

Avatar for zoops

zoops

November 20, 2018

Other Decks in Technology

Transcript

  1. • 블록체인 • 소개 • 합의 알고리즘 소개 • 필요성

    • FLP impossibility (피셔-린치-패터슨의 합의 불가능 ) • POW 소개 • POS 소개 • DPOS 소개 • PIVX • POW • POS 블록체인의 합의 알고리즘에 대해서
  2. 잠깐 – UTXO 란 - UTXO : Unspent Transaction Output

    - 소비되지 않은 출력값 - 절대로 쪼개지지 않는다 (1회성이다) - 일부가 소비될때는 - 입력 UTXO 는 폐기 - 소비되는 주소에 새로운 UTXO 생성 - 본 주소에 남은 코인을 가진 새로운 UTXO 생성 - 여러 UTXO 가 합쳐져서 소비될때도 동일 - 주소에 연결된 UTXO 총합이 주소가 가진 코인의 수량 - 비트코인 거래란 UTXO 가 소멸되고, 새롭게 생성되는 과정.
  3. 합의알고리즘 필요성 - 비동기 네트워크에서 중앙서버가 없는 분산서버들 간의 (각

    노드들간의) 데이터 정합을 위한 알고 리즘 - 블록체인 - 블록체인은 중앙서버가 없다. - P2P 비동기 네트워크를 사용한다.  따라서 블록체인은 합의 알고리즘이 필요하다. - 합의 알고리즘은 블록체인 이전에도 분산서버 도메인에서 오랫동안 연구되어온 과제. - 비트코인의 POW 는 합의 알고리즘의 한 형태 (특이한)
  4. FLP impossibility - 피셔-린치-패터슨의 합의 불가능 문제 - 우선 아무

    문제 없는 두 노드가 서로 다른 값으로 합의하면 안 된다. - 블록체인 관점에서 보면 같은 높이에 서로 다른 블록이 생성됐다는 것이다.이런 특성을 분산 시스템에서는 consensus의 safety라고 말한다. - 합의가 언젠가는 이루어져야 한다. - 분산 시스템에서 합의는 노드 간의 메시지를 주고받으며 각 노드의 상태를 변경시키며 이루어진다. 이때 문제없는 노드 들은 무한 루프에 빠지지 않고 반드시 상태 변경이 종료돼야 한다. - 모든 노드가 문제없이 합의를 할 수 있으면 이 시스템은 liveness가 보장된다고 말한다. - Safety : "문제없는 노드 사이에서는 잘못된 합의가 이루어지지 않는다." - Liveness : "문제없는 노드들은 반드시 합의를 한다"라는 것이다. - FLP impossibility 증명 - 비동기 분산 네트웍에서 safety와 liveness를 둘 다 만족하는 합의 알고리즘이 존재할 수 없다. - 합의 알고리즘을 선택한다는 것은 사실상 safety와 liveness 중 무엇을 선택하고 무엇을 버릴까 하는 문제이다. - 예 > POW (nakamoto consensus) - 지금 있는 체인보다 더 긴 체인을 만들 해시 파워만 있으면 언제든지 현재 합의된 블록을 다른 블록으로 대체할 수 있다. - 이런 방식을 블록체인에서는 finality가 보장되지 않는다고 말하고 FLP impossibility에서는 liveness를 위해서 safety를 포기했다고 말한다.  하지만 확률적인 부분과 보상과 손해의 경제적 유인에 의해 사실상 safety 를 보완
  5. 분산 네트워크에서 노드들 간의 문제점 - 비잔틴 장군 문제 -

    노드내에 약속된 행동을 하지 않는 노드(비잔틴 노드)가 존재할때 문제점. - 해결방법 - 모든 노드들은 블록을 만들때 해쉬파워나 지분을 이용하게함. - 그렇게 만들어진 블록을 검증 노드(다른 노드)에게 보냄 - 다른 노드들은 해쉬파워나 지분을 보고 검증함 - 다른 노드가 속이기 위해서는 기존 블록 생성을 위한 해쉬파워나 지분보다 큰 해쉬파워나 지분을 소비하여야함. - 그렇게 속여도 51%의 노드가 속지 않으면 소용 없음. - 시빌어택 문제 == 51% 공격 문제(spawn camp) ?? - 다수가 합의해야하는 상황에서 하나의 노드가 다수인것처럼 하여 공격하는 문제 - 51% 의 노드가 공격을 하면 올바른 합의가 불가능해짐의 문제점. - 해결방법 - 해쉬파워를 이용하거나 지분을 이용하여 51% 를 점유하기 어렵게 만듬. - 또한 51% 를 점유할만큼의 능력이 있어도 보상과 손해의 경제적 유인으로 공격을 하게되 면 가치가 떨어질것임으로 그렇게 하지 않을꺼라는 암묵적 믿음 -
  6. 블록체인에서 합의 알고리즘이란 - 블록 생성 권한 분배 및 검증

    방법 - 누가 블록을 채굴을 할 것, (즉, 채굴확률을 어떻게 결정할 것)인지 - 포크시 하나의 블록체인 선택 방법 - 어느 체인이 유효한지 에 대한 룰 - 누가 블록을 채굴할것인지 - POW : 해시값을 찾아낸 노드 (해시 파워를 증명한 노드) - 어느 체인이 유효한지 - POW : - 더 어려운 해시값을 찾아낸 노드 - 더 긴 체인 (더 많은 해시 파워를 소유한 체인)
  7. 합의 알고리즘 종류 - FLP impossibility (피셔-린치-패터슨의 합의 불가능) 문제에서

    다뤘듯 비동기 분산 네트워크에서 완벽 하게 만족하는 합의 알고리즘은 존재하지 않음. - 시스템의 성격이나 컨셉에 의해 수 많은 합의 알고리즘이 존재 - POW - POS - DPOS - BFT - PBFT - POA - POWeight - Hashgraph - Block-Lattice - SPECTRE - DAG - 등등
  8. POW (Proof of Work) 간략소개 - POW (Proof of Work)

    - 비트코인 등 - 네트워크에 있는 채굴자들이 독자적으로 해시 계산(블록해시를 계산 함)을 하고,이것이 특정 목표보다 작거나 같으면 해당 블록을 네트워크에 전파하고 다른 노드들은 검증한 이후 해당 블록은 체택하고 다음 블록해시를 계산 - 51% 공격에 취약 - 51% 의 해시파워를 얻는데 드는 비용 약 3000억 - 현재 몇 개의 중국 채굴장이 51% 를 점유 - 전력 및 자원의 낭비 - 불특정 다수의 노드의 합의로 인한 확장성 문제 -
  9. POS (Proof of Stake) 간략소개 - POS (Proof of Stake)

    - 에이다 등 - 네트워크의 채굴자들이 암호화폐를 보유하고 채굴에 할당 시켜 놓으므로써 보유한 양에 비례 해 블록 생성할 권한을 얻게 되는 방법 - 51% 공격이 비교적 어려움 - 51%의 자본의 독점필요. - 해시파워 비용보다 코인 시총 비용이 더 큼 (비트코인 1120억 달러) - 전력 및 자원이 비교적 적음. - 자본주의 문제 (부익부 빈익빈) - 많은 자본을 가진 노드가 보상을 많이 받고 계속 부자가 된다. - 보유기간까지 생각하는 알고리즘으로 보완 - Nothing of Stake 문제 - 포크시에 특정 블록을 선택하지 않고 모든 블록을 선택하는 문제 - 블록 선택시 배팅(Stake) 하고 실패하는 블록을 선택시 지분을 빼앗는 방법으로 보완 - 초반엔 작은 지분 배팅 - 블록이 커질수록 큰 지분 배팅 - 불특정 다수의 노드의 합의로 인한 확장성 문제
  10. DPOS (Delegate Proof of Stake) - DPOS (Delegate Proof os

    Stake) - 이오스등 - 투표를 통해 선출된 대표자(증인) 들만의 합의로 블록 생성 - 전력 및 자원이 비교적 적음. - 적은 노드의 합의로 인한 확장성 증가 - 중앙화로 회귀 - 노출된 대표자(증인)에 대한 공격 위험 - 문제가 있는 증인은 예비증인으로 대체 - 예비증인도 문제가 있으면 블록 멈출 수 있음.
  11. POW – BlockHash • 우리가 기대하는 Hash – Ca2099f4706a7b28c5550b304d1f51ef61389617358b45d9714de5f2699638fe •

    BitcoinHash – 400,000 번 블록 • 000000000000000004ec466ce4732fe6f1ed1cddc2ed4b328fff5224276e3f6f – 400,001 번 블록 • 000000000000000005421b1b2ee6d06d037557d7f5ec96852542413cfed40c22 – 400,002 번 블록 • 0000000000000000016578099aab6d26d41c8815e9ab5f204f505ba4ac3c084d – 400,003 번 블록 • 0000000000000000053c5d6913444bcef2a5a2a6ec84cb0dbaef93e6ad3074ba
  12. POW - nBits • Bitcoin 40,000 block – Hash •

    000000000000000004ec466ce4732fe6f1ed1cddc2ed4b328fff5224276e3f6 f – nBits • 0x1806B99F • 000000000000000006BB9F00000000000000000000000000000000000000 0000
  13. PIVX - 1블록 : 제니시스 블록 - ~259200 블록 :

    POW (Quark) - ~ Infinite : POS (SHA256) - PIVX 는 POW 와 POS 를 모두 사용
  14. PIVX - POW - miner.cpp - void BitcoinMiner(CWallet* pwallet, bool

    fProofOfStake) void BitcoinMiner(CWallet* pwallet, bool fProofOfStake) { LogPrintf("CLINKMiner started\n"); SetThreadPriority(THREAD_PRIORITY_LOWEST); RenameThread("clink-miner"); // Each thread has its own key and counter CReserveKey reservekey(pwallet); unsigned int nExtraNonce = 0; while (fGenerateBitcoins || fProofOfStake) { if (fProofOfStake) { ……… ……… } // // Create new block … … … … … … IncrementExtraNonce(pblock, pindexPrev, nExtraNonce); //Stake miner main if (fProofOfStake) { // for POS … … … … … … continue; } //=========================================================================================================================== // for POW … … … … … … }
  15. PIVX – POW int64_t nStart = GetTime(); uint256 hashTarget =

    uint256().SetCompact(pblock->nBits); while (true) { unsigned int nHashesDone = 0; uint256 hash; while (true) { // GetHash…. ………… ………… } // Check for stop or if block needs to be rebuilt boost::this_thread::interruption_point(); // Regtest mode doesn't require peers if (vNodes.empty() && Params().MiningRequiresPeers()) break; if (pblock->nNonce >= 0xffff0000) break; if (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && GetTime() - nStart > 60) break; if (pindexPrev != chainActive.Tip()) break; ………… ………… // Update nTime every few seconds UpdateTime(pblock, pindexPrev); if (Params().AllowMinDifficultyBlocks()) { // Changing pblock->nTime can change work required on testnet: hashTarget.SetCompact(pblock->nBits); } } while (true) { hash = pblock->GetHash(); if (hash <= hashTarget) { // Found a solution SetThreadPriority(THREAD_PRIORITY_NORMAL); LogPrintf("BitcoinMiner:\n"); LogPrintf("proof-of-work found \n hash: %s \ntarget: %s\n", hash.GetHex(), hashTarget.GetHex()); ProcessBlockFound(pblock, *pwallet, reservekey); SetThreadPriority(THREAD_PRIORITY_LOWEST); // In regression test mode, stop mining after a block is found. This // allows developers to controllably generate a block on demand. if (Params().MineBlocksOnDemand()) throw boost::thread_interrupted(); break; } pblock->nNonce += 1; nHashesDone += 1; if ((pblock->nNonce & 0xFF) == 0) break; } - miner.cpp - void BitcoinMiner(CWallet* pwallet, bool fProofOfStake)
  16. PIVX - POS - miner.cpp - void BitcoinMiner(CWallet* pwallet, bool

    fProofOfStake) void BitcoinMiner(CWallet* pwallet, bool fProofOfStake) { LogPrintf("CLINKMiner started\n"); SetThreadPriority(THREAD_PRIORITY_LOWEST); RenameThread("clink-miner"); // Each thread has its own key and counter CReserveKey reservekey(pwallet); unsigned int nExtraNonce = 0; while (fGenerateBitcoins || fProofOfStake) { if (fProofOfStake) { ……… ……… } // // Create new block … … … … … … IncrementExtraNonce(pblock, pindexPrev, nExtraNonce); //Stake miner main if (fProofOfStake) { // for POS … … … … … … continue; } //=========================================================================================================================== // for POW … … … … … … }
  17. PIVX – POS - wallet.cpp - bool CWallet::CreateCoinStake bool CWallet::CreateCoinStake(const

    CKeyStore& keystore, unsigned int nBits, int64_t nSearchInterval, CMutableTransaction& txNew, unsigned int& nTxNewTime) { ……… ……… ……… // Get the list of stakable inputs std::list<std::unique_ptr<CStakeInput> > listInputs; if (!SelectStakeCoins(listInputs, nBalance - nReserveBalance)) return false; ……… ……… ……… for (std::unique_ptr<CStakeInput>& stakeInput : listInputs) { ……… ……… ……… //iterates each utxo inside of CheckStakeKernelHash() if (Stake(stakeInput.get(), nBits, block.GetBlockTime(), nTxNewTime, hashProofOfStake)) { ……… ……… ……… } ……… ……… ……… } ……… ……… ………
  18. PIVX – POS - kernel.cpp - bool Stake(CStakeInput* stakeInput, unsigned

    int nBits, unsigned int nTimeBlockFrom, - unsigned int& nTimeTx, uint256& hashProofOfStake) bool stakeTargetHit(uint256 hashProofOfStake, int64_t nValueIn, uint256 bnTargetPerCoinDay) { //get the stake weight - weight is equal to coin amount uint256 bnCoinDayWeight = uint256(nValueIn) / 100; // Now check if proof-of-stake hash meets target protocol bool res = hashProofOfStake < (bnCoinDayWeight * bnTargetPerCoinDay); return res; } bool CheckStake(const CDataStream& ssUniqueID, CAmount nValueIn, const uint64_t nStakeModifier, const uint256& bnTarget, unsigned int nTimeBlockFrom, unsigned int& nTimeTx, uint256& hashProofOfStake) { CDataStream ss(SER_GETHASH, 0); ss << nStakeModifier << nTimeBlockFrom << ssUniqueID << nTimeTx; hashProofOfStake = Hash(ss.begin(), ss.end()); return stakeTargetHit(hashProofOfStake, nValueIn, bnTarget); } bool Stake(CStakeInput* stakeInput, unsigned int nBits, unsigned int nTimeBlockFrom, unsigned int& nTimeTx, uint256& hashProofOfStake) { //grab difficulty uint256 bnTargetPerCoinDay; bnTargetPerCoinDay.SetCompact(nBits); //grab stake modifier uint64_t nStakeModifier = 0; if (!stakeInput->GetModifier(nStakeModifier)) return error("failed to get kernel stake modifier"); CDataStream ssUniqueID = stakeInput->GetUniqueness(); CAmount nValueIn = stakeInput->GetValue(); for (int i = 0; i < nHashDrift; i++) //iterate the hashing { if (!CheckStake(ssUniqueID, nValueIn, nStakeModifier, bnTargetPerCoinDay, nTimeBlockFrom, nTryTime, hashProofOfStake)) continue; fSuccess = true; // if we make it this far then we have successfully created a stake hash } return fSuccess; }
  19. Beyond Mobile, Beyond Smart THANK YOU (주)모베란 오피스 : 인천광역시

    연수구 송도동 송도과학로 32, 30층 M3001호 Tel 070-4245-3267 http://www.moberan.com 백지훈, ㈜ 모베란 대표 [email protected]