스위프트로 배우는 블록체인 - 탈중앙화 구현


노드모듈생성

지금까지는 하나의 네트워크에서 블록체인이 어떻게 작동하는지 알아보았습니다. 지금부터는 여러개의 노드를 만들어서 탈중앙화 개념을 구현해 보도록 하겠습니다. model.swift에 새로운 노드를 생성할 클래스를 아래와 같이 작성해 줍니다.

//새로운 노드 생성 클래스

class BlockchainNode : Codable {

    var address : String

    init(address : String) {

        self.address = address

    }

}


아래에 이이서 class Blockchain 부분에 아래에 위에서 만든 노드 데이터를 컨트롤할 변수와 추가할 함수를 만들어 준다.

//체인 구조체

class Blockchain : Codable {

    //블록이 배열형태로 저장됨

    private (set) var blocks : [Block] = [Block]()

   

    //추가! 블록체인 데이터 구조에 블록체인 배열 값을 가지는 변수 생성

    private (set) var nodes : [BlockchainNode] = [BlockchainNode]()


    //추가! 블록체인 데이터 구조에 노드를 추가하는 함수

    func addNode(_ node : BlockchainNode){

        self.nodes.append(node)


}



마지막으로 이번에는 제일 위에서 만든 BlockchainNode 클래스에 아래와 같이 코드를 추가해 준다. 블록체인컨트롤.swift에서  웹브라우저로 넘어오는 request 데이터로 이 클래스를 초기화 해주기 위해서 아래 코드를 추가한다.

//새로운 노드 생성 클래스

class BlockchainNode : Codable {

    var address : String

    

    //BlockchainController.swift 에서 request 로 넘어오는 데이터로 초기화 하기 위한 초기화 함수

    init?(request : Request){

        

        guard let address = request.data["address"]?.string else {

            return nil

        }

        self.address = address

    }

    

    init(address : String) {

        self.address = address

    }

}


노드등록

노드를 생성하는 함수를 만들었으니 이번에는 생성된 노드를 등록하는 함수를 구현해보겠습니다. BlockchainService 클래스로 가서 아래 코드를 추가해준다. //추가! 부분이다.

class BlockchainService {

    

    //체인배열 변수

    private (set) var blockchain : Blockchain!

    

    //제네시스 블럭 초기화=

    init() {

        self.blockchain = Blockchain(genesisBlock: Block())

        

    }

    

    //추가! 생성한 노드를 블록체인에 추가하는 함수

    func registerNode(_ node : BlockchainNode){

            self.blockchain.addNode(node)

}


이어서 이제 BlockchainController.swift로 와서 func setupRoutes(){} 함수 부분에 웹브라우저를 통해서 노드를 등록하고, 등록한 노드를 확인해주는 로직을 작성해보겠다. 아래 소스 코드 참고.

    private func setupRoutes(){

        

        //노드 등록

        self.drop.post("/nodes/register"){ request in

            if let blockchainNode = BlockchainNode(request: request){

                self.blockchainService.registerNode(blockchainNode)

            }

            return try JSONEncoder().encode(["msg":"노드 등록 성공"])

        }

        

        //노드 확인

        self.drop.get("/nodes"){request in

            let nodes = self.blockchainService.blockchain.nodes

            return try JSONEncoder().encode(nodes)

}

테스트

위에 소스가 잘 작동을 하는지 포스트맨을 통해서 확인해보자~


등록된노드 확인 (8080,8088 등 여러개 등록해서 확인해보자)



여러 노드에서 마이닝 구현


vapor 프레임워크를 통해서 여러 포트의 서버를 등록해보겠다. 터미널을 열고 작업폴더에 위치한다음에 

vapor run --port=8080, vapor run --port=8090, vapor run --port=8010 등 여러 서버가 가동되게 한다. 그리고 반드시 웹브라우저에서 확인 해야 한다.


마지막 구현

모든 노드들이 데이터를 공유하게 하기 위한 코드를 작성해보자. 일단 Blockchain 클래스에 blocks 변수 앞에 private 키워드 제거해준다.

//체인 구조체

class Blockchain : Codable {

    //블록이 배열형태로 저장됨

    var blocks : [Block] = [Block]()


service 부분에 아래 함수 추가

    func resolve(completion : @escaping (Blockchain) -> ()){

        

        let nodes = self.blockchain.nodes

        for node in nodes{

            let url = URL(string: "http://\(node.address)/blockchain")!

            URLSession.shared.dataTask(with: url){ data,_, _ in

                if let data = data{

                    let blockchain = try! JSONDecoder().decode(Blockchain.self, from: data)

                    if self.blockchain.blocks.count > blockchain.blocks.count{

                        completion(self.blockchain)

                    }else{

                        self.blockchain.blocks = blockchain.blocks

                        completion(blockchain)

                    }

                }

            }.resume()

        }

}

controller 부분에 아래 함수 추가

    private func setupRoutes(){

        self.drop.get("/nodes/resolve"){request in

            return try Response.async{

                portal in

                self.blockchainService.resolve(completion: { (blockchain) in

                    let blockchain = try! JSONEncoder().encode(blockchain)

                    portal.close(with: blockchain.makeResponse())

                })

            }

}


테스트

post맨을 열어서 한번더 테스트를 해보자.







스위프트로 배우는 블록체인 - 데이터구조


순서

xcode9열기 -> get Started with a playground -> 위쪽 탭에 mac os 선택 -> blank 선택


개요

이번 포스팅에서는 블록체인 기술의 뼈대가 되는 데이터 구조를 만들어 보겠습니다. 먼저 거래를 담당하는 transaction 구조체, 거래내역과 해쉬, 이전해쉬값, nonce 값을 담는 block 구조체를 만들고 그 블록을 담을 blockchain 구조체를 만들어 보겠습니다. 위에서 오픈한 mac os playground를 열고 아래 코드를 작성해주세요.


transaction 구조체

//거래 데이터 구조체

class Transaction{

    var from: String

    var to: String

    var amount: Double

    //초기화

    init(from:String,to:String,amount:Double) {

        self.from = from

        self.to = to

        self.amount = amount

    }

    }


block 구조체

//블록 구조체

class Block{

    //번호, 이전해쉬,해쉬,nonce를 가지고 있다.

    var index : Int = 0

    var previousHash : String = ""

    var hash: String!

    var nonce : Int

    //거래 내역을 가지고 있다.

    private (set) var transactions : [Transaction] = [Transaction]()

    

    init(){

        self.nonce = 0

    }

}


blockchain구조체

//체인 구조체

class BlockChain {

    //블록이 배열형태로 저장됨

    private (set) var blocks : [Block] = [Block]()

}



key생성하기

먼저 class구조체를 json형식으로 사용할 수 있게 하기 위해서 class type을 Codable로 지정해줍니다. class Block : Codable{} , 모든class에 지정! 그리고 key를 Blok class의 getter 함수 key 를 만들어 주고, 그 아래 거래가 발생할때 거래 내역을 담아 줄 배열을 만들어 줍니다.

    //key 변수

    var key : String {

        get{

            //위 transaction 배열을 json 형식으로 변경

            let transactionsData = try! JSONEncoder().encode(self.transactions)

            // json형식의 transaction 배열을 String 값으로 변경

            let transactionsJSONString = String(data: transactionsData, encoding:.utf8)

            //번호, 이전해쉬, nonce + transactionString 값을 이용해서 고유 key 생성

            return String(self.index) + self.previousHash + String(self.nonce) + transactionsJSONString!

        }

    }


    //거래 내역을 담는 함수

    func addTransaction(transaction: Transaction){

        self.transactions.append(transaction)

    }


그리고 맨 아래 부분에서 거래를 한번 발생시키고, 새로운 블럭과 key를 만들어 봅시다.

let transaction = Transaction(from: "kim", to: "hong", amount: 1000)

let block1 = Block()

block1.addTransaction(transaction: transaction)

block1.key


Blockchain 구조체 초기화

이 클래스에서는 blocks 배열에 아무런 블럭이 없으면 현재 블록개수는 0이기 때문에 제네시스 블럭, 즉 첫번째 블록을 만드는 소스를 추가하고, blocks 배열에 추가해 주는 로직을 작성합니다. 그리고 해쉬값을 생성해주는 함수를 만들어서호출 하면 해쉬값을 리턴시켜줍니다. 이때 mac os 내장 모듈인 sha1Hash를 사용합니다.

//체인 구조체

class Blockchain : Codable {

    //블록이 배열형태로 저장됨

    private (set) var blocks : [Block] = [Block]()

    

    //초기화

    init(genesisBlock : Block){

        addBlock(genesisBlock)

    }

    

    //블록체인 구조체에 블록을 추가하는 함수

    private func addBlock(_ block : Block){

        //체인에 아무런 블록이 없으면 제네시스 블록 생성

        if self.blocks.isEmpty{

            //제네시스 블록의 이전 해쉬값 (임의지정)

            block.previousHash = "0000000000"

            //제네시스 블록의 해쉬값

            block.hash = generateHash(for :block)

        }

        //삽입

        self.blocks.append(block)

    }

    

    //해쉬 생성 함수

    func generateHash(for block : Block) -> String{

        //block의 key 값을 이용해서 hash 값을 만들어 낸다.

        let hash = block.key.sha1Hash()

        return hash

    }

}

sha1Hash 코드작성

// String 확장

extension String {

    

    func sha1Hash() -> String {

        

        let task = Process()

        task.launchPath = "/usr/bin/shasum"

        task.arguments = []

        

        let inputPipe = Pipe()

        

        inputPipe.fileHandleForWriting.write(self.data(using: String.Encoding.utf8)!)

        

        inputPipe.fileHandleForWriting.closeFile()

        

        let outputPipe = Pipe()

        task.standardOutput = outputPipe

        task.standardInput = inputPipe

        task.launch()

        

        let data = outputPipe.fileHandleForReading.readDataToEndOfFile()

        let hash = String(data: data, encoding: String.Encoding.utf8)!

        return hash.replacingOccurrences(of: "  -\n", with: "")

    }

}


제네시스 블록생성 후 체인에 추가

//제네시스 블록 생성

let genesisBlock = Block()


//추가

let blockchain = Blockchain(genesisBlock: genesisBlock)



전체소스코드

//: Playground - noun: a place where people can play


/*

 

 

 

 */




import Cocoa


//거래 데이터 구조체

class Transaction : Codable{

    var from: String

    var to: String

    var amount: Double

    //초기화

    init(from:String,to:String,amount:Double) {

        self.from = from

        self.to = to

        self.amount = amount

    }

    

}


//블록 구조체

class Block: Codable{

    //번호, 이전해쉬,해쉬,nonce를 가지고 있다.

    var index : Int = 0

    var previousHash : String = ""

    var hash: String!

    var nonce : Int


    //거래 내역을 가지고 있다.

    private (set) var transactions : [Transaction] = [Transaction]()

    

    //key 변수

    var key : String {

        get{

            //위 transaction 배열을 json 형식으로 변경

            let transactionsData = try! JSONEncoder().encode(self.transactions)

            // json형식의 transaction 배열을 String 값으로 변경

            let transactionsJSONString = String(data: transactionsData, encoding:.utf8)

            //번호, 이전해쉬, nonce + transactionString 값을 이용해서 고유 key 생성

            return String(self.index) + self.previousHash + String(self.nonce) + transactionsJSONString!

        }

    }

    //거래 내역을 담는 함수

    func addTransaction(transaction: Transaction){

        self.transactions.append(transaction)

    }


    //초기화

    init(){

        self.nonce = 0

    }

}


//체인 구조체

class Blockchain : Codable {

    //블록이 배열형태로 저장됨

    private (set) var blocks : [Block] = [Block]()

    

    //초기화

    init(genesisBlock : Block){

        addBlock(genesisBlock)

    }

    

    //블록체인 구조체에 블록을 추가하는 함수

    private func addBlock(_ block : Block){

        //체인에 아무런 블록이 없으면 제네시스 블록 생성

        if self.blocks.isEmpty{

            //제네시스 블록의 이전 해쉬값 (임의지정)

            block.previousHash = "0000000000"

            //제네시스 블록의 해쉬값

            block.hash = generateHash(for :block)

        }

        //삽입

        self.blocks.append(block)

    }

    

    //해쉬 생성 함수

    func generateHash(for block : Block) -> String{

        //block의 key 값을 이용해서 hash 값을 만들어 낸다.

        let hash = block.key.sha1Hash()

        return hash

    }

}


//제네시스 블록 생성

let genesisBlock = Block()

//추가

let blockchain = Blockchain(genesisBlock: genesisBlock)



let transaction = Transaction(from: "kim", to: "hong", amount: 1000)

let block1 = Block()

block1.addTransaction(transaction: transaction)

block1.key







// String 확장

extension String {

    

    func sha1Hash() -> String {

        

        let task = Process()

        task.launchPath = "/usr/bin/shasum"

        task.arguments = []

        

        let inputPipe = Pipe()

        

        inputPipe.fileHandleForWriting.write(self.data(using: String.Encoding.utf8)!)

        

        inputPipe.fileHandleForWriting.closeFile()

        

        let outputPipe = Pipe()

        task.standardOutput = outputPipe

        task.standardInput = inputPipe

        task.launch()

        

        let data = outputPipe.fileHandleForReading.readDataToEndOfFile()

        let hash = String(data: data, encoding: String.Encoding.utf8)!

        return hash.replacingOccurrences(of: "  -\n", with: "")

    }

}





특정값에 해당하는 hash값 리턴

위에서 block의 key값을 sha1Hash() 함수로 바꾸어서 임의의 문자열데이터로 만들어 주었다. 여기서 조건을 부여해서 해쉬 값이 특정조건에 맞으면 그 값을 리턴하게 하는 코드를 작성해 보겠습니다. class Blockchain (){} 함수 안에 있는 해쉬 생성 함수를 아래와 같이 변경 해줍니다.


    //해쉬 생성 함수

    func generateHash(for block : Block) -> String{

        //block의 key 값을 이용해서 hash 값을 만들어 낸다.

        var hash = block.key.sha1Hash()

        // 특정값 (앞 2자리가 00 인 hash 값 구하기

        while(!hash.hasPrefix("00")){

            //조건이 맞지 않을 경우 block의 noce 값 증가

            block.nonce += 1

            hash = block.key.sha1Hash()

            print(hash)

        }

        

        return hash


}


새로운 블럭생성 함수

새로운 블럭에는 항상 이전 블럭의 해쉬값, 자신의 번호 , 자신의 해쉬 값이 들어갑니다. class Blockchain (){} 함수 안에 작성

    //새로운 블락 구하는 함수, 다음 블록 생성

    func getNextBlock(transactions:[Transaction]) ->Block{

        //새 블록 객체

        let block = Block()

        //새로운 블록이 생성될때는 이전 거래 내역이 배열로 들어간다.

        transactions.forEach { (transaction) in

            block.addTransaction(transaction: transaction)

        }

        //새로운 블록에는 이전 블록의 hash 값, 번호, 자신의 hash 값이 들어간다.

        let previousBlock = getPreviousBlock()

        block.index = self.blocks.count

        block.previousHash = previousBlock.hash

        block.hash = generateHash(for: block)

        return block

    }


이전 블럭가져오기

이전블록의 해쉬값을 가져오기 위해서 이전 블록을 가져오는 함수를 만들어보겠습니다.  위의 새로운 블럭 구하는 함수 코드 아래에 작성

    //이전 블럭 가져오기

    private func getPreviousBlock() -> Block {

        return self.blocks[self.blocks.count - 1]

    }



새로운 거래와 새로운 블록 생성

새로운 거래를 발생시키는 Transaction 함수를 이용해서 거래 내역을 만들고 이것을 다음에 생성될 새로운 블록안에 넣어주었다. 그리고 새로 생성된 블록은 blockchain 안에 있는 블록의 배열 안에 넣어주었다. 그리고 체인안에 존재하는 블록의 개수를 찍어 보았다. 총 2가 나온다. 처음만든 제네시스 블록 하나, 그리고 코드로 만들어준 블록 하나 총 2개다. 참고로 addBlock 함수에 접근하기 위해서 addBlock 함수 앞에 있는 private 키워드를 지워주자.

//제네시스 블록 생성

let genesisBlock = Block()

//추가

let blockchain = Blockchain(genesisBlock: genesisBlock)


//새로운 거래 발생

let transaction = Transaction(from: "kim", to: "hong", amount: 1000)


print("--------------------------------------------------------")

//위에서 발생한 거래내역을 새로운 블럭을 생성하는 함수안에 넣어주었다.

let block = blockchain.getNextBlock(transactions: [transaction])

//새로만든 블록을 넣어주고

blockchain.addBlock(block)

//블록의 총 개수를 확인해보자.

print(blockchain.blocks.count)


결과확인


코드 정리




import Cocoa


//거래 데이터 구조체

class Transaction : Codable{

    var from: String

    var to: String

    var amount: Double

    //초기화

    init(from:String,to:String,amount:Double) {

        self.from = from

        self.to = to

        self.amount = amount

    }

    

}


//블록 구조체

class Block: Codable{

    //번호, 이전해쉬,해쉬,nonce를 가지고 있다.

    var index : Int = 0

    var previousHash : String = ""

    var hash: String!

    var nonce : Int


    //거래 내역을 가지고 있다.

    private (set) var transactions : [Transaction] = [Transaction]()

    

    //key 변수

    var key : String {

        get{

            //위 transaction 배열을 json 형식으로 변경

            let transactionsData = try! JSONEncoder().encode(self.transactions)

            // json형식의 transaction 배열을 String 값으로 변경

            let transactionsJSONString = String(data: transactionsData, encoding:.utf8)

            //번호, 이전해쉬, nonce + transactionString 값을 이용해서 고유 key 생성

            return String(self.index) + self.previousHash + String(self.nonce) + transactionsJSONString!

        }

    }

    //거래 내역을 담는 함수

    func addTransaction(transaction: Transaction){

        self.transactions.append(transaction)

    }


    //초기화

    init(){

        self.nonce = 0

    }

}


//체인 구조체

class Blockchain : Codable {

    //블록이 배열형태로 저장됨

    private (set) var blocks : [Block] = [Block]()

    

    //초기화

    init(genesisBlock : Block){

        addBlock(genesisBlock)

    }

    

    //블록체인 구조체에 블록을 추가하는 함수

     func addBlock(_ block : Block){

        //체인에 아무런 블록이 없으면 제네시스 블록 생성

        if self.blocks.isEmpty{

            //제네시스 블록의 이전 해쉬값 (임의지정)

            block.previousHash = "0000000000"

            //제네시스 블록의 해쉬값

            block.hash = generateHash(for :block)

        }

        //삽입

        self.blocks.append(block)

    }

    

    //해쉬 생성 함수

    func generateHash(for block : Block) -> String{

        //block의 key 값을 이용해서 hash 값을 만들어 낸다.

        var hash = block.key.sha1Hash()

        // 특정값 (앞 2자리가 00 인 hash 값 구하기

        while(!hash.hasPrefix("00")){

            //조건이 맞지 않을 경우 block의 noce 값 증가

            block.nonce += 1

            hash = block.key.sha1Hash()

            print(hash)

        }

        

        return hash

    }

    

    //새로운 블락 구하는 함수, 다음 블록 생성

    func getNextBlock(transactions:[Transaction]) ->Block{

        //새 블록 객체

        let block = Block()

        //새로운 블록이 생성될때는 이전 거래 내역이 배열로 들어간다.

        transactions.forEach { (transaction) in

            block.addTransaction(transaction: transaction)

        }

        //새로운 블록에는 이전 블록의 hash 값, 번호, 자신의 hash 값이 들어간다.

        let previousBlock = getPreviousBlock()

        block.index = self.blocks.count

        block.previousHash = previousBlock.hash

        block.hash = generateHash(for: block)

        return block

    }

    

    //이전 블럭 가져오기

    private func getPreviousBlock() -> Block {

        return self.blocks[self.blocks.count - 1]

    }

}


//제네시스 블록 생성

let genesisBlock = Block()

//추가

let blockchain = Blockchain(genesisBlock: genesisBlock)


//새로운 거래 발생

let transaction = Transaction(from: "kim", to: "hong", amount: 1000)


print("--------------------------------------------------------")

//위에서 발생한 거래내역을 새로운 블럭을 생성하는 함수안에 넣어주었다.

let block = blockchain.getNextBlock(transactions: [transaction])

//새로만든 블록을 넣어주고

blockchain.addBlock(block)

//블록의 총 개수를 확인해보자.

print(blockchain.blocks.count)



//let block1 = Block()

//block1.addTransaction(transaction: transaction)

//block1.key







// String 확장

extension String {

    

    func sha1Hash() -> String {

        

        let task = Process()

        task.launchPath = "/usr/bin/shasum"

        task.arguments = []

        

        let inputPipe = Pipe()

        

        inputPipe.fileHandleForWriting.write(self.data(using: String.Encoding.utf8)!)

        

        inputPipe.fileHandleForWriting.closeFile()

        

        let outputPipe = Pipe()

        task.standardOutput = outputPipe

        task.standardInput = inputPipe

        task.launch()

        

        let data = outputPipe.fileHandleForReading.readDataToEndOfFile()

        let hash = String(data: data, encoding: String.Encoding.utf8)!

        return hash.replacingOccurrences(of: "  -\n", with: "")

    }

}

자바스크립트로 블록체인 구현 강좌 11 - 나만의 비트코인 발행하기

지난 포스팅에서 하나의 네트워크에서 블록체인이 어떻게 작동이 되는지 살펴보았다. 이번포스팅에서는 여러개의 노드, 즉 컴퓨터들이 참여를 할때 블록체인 데이터가 어떻게 기록되는지 살펴보겠다.

순서

1. api.js 파일 이름을 networkNode.js 로 변경하자. 

2. networkNode.js 파일 윗 부분에 동적 포트관련 변수 선언해준다.

//동적 포트 package.json script 객체에서 2번째 방에 들어있는 데이터 3001,3002,3003 ...3005
var port = process.argv[2];

3. app.listen 을 아래와 같이 바꿔 준다.

//동적 포트
app.listen(port,function(){
console.log(`listening on port ${port}...`)
})

4. package.json 부분에서 script 부분을 아래와 같이 바꿔 준다.

"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"node_1":"nodemon --watch dev -e js dev/networkNode.js 3001 http://localhost:3001",
"node_2":"nodemon --watch dev -e js dev/networkNode.js 3002 http://localhost:3002",
"node_3":"nodemon --watch dev -e js dev/networkNode.js 3003 http://localhost:3003",
"node_4":"nodemon --watch dev -e js dev/networkNode.js 3004 http://localhost:3004",
"node_5":"nodemon --watch dev -e js dev/networkNode.js 3005 http://localhost:3005"
},



이제 포트 3001 부터 3005번 까지의 node(서버)를 실행시킬 수 있다. 실행방법은 아래와 같다.

1. 터미널 열기 

2. 개발폴더에 위치하고

3. npm run node_1

4. 터미널 창 하나 더 뛰워서 npm run node_2  반복적으로 실행



blockchain.js로 이동

//sha256 모듈을 가져다 쓰겠다.
const sha256 = require('sha256');

//현재 노드의 url -- package.json script 객체에서 3번째 방에 들어있는 데이터 http://localhost:3001
const currentNodeUrl = process.argv[3];

//블록체인 데이터 구조
function Blockchain(){
this.chain = [];
this.pendingTransaction = [];
//현재 node url -- 이부분!!!
this.currentNodeUrl = currentNodeUrl;
this.networkNodes = [];

//제네시스 블락 - 임의의 인자값 넣어준다.
this.createNewBlock(100,'0','0')
}


sha 256모듈 변수 아래에 현재 노드의 url을 알 수 있는 코드를 작성하고 function blockchain(){} 함수 안에 //현재 node url 주석 아래 두 코드를 작성해준다. 이건 접속한 node의 url 데이터를 저장하겠다는 뜻.


새로운 노드가 기존의 네트워크에 진입하는과정 (탈중앙화된 네트워크 그림)

1. 새로운 노드가 기존의 노드 네트워크에 들어가기전에 등록을 거친 후 알린다.

2. 각 노드들에게 새로운 노드 정보를 등록시켜 준다.

3.기존의 모든 노드의 데이터를 새로운 노드에게 등록한다.


소스(networkNode.js에 작성)

//새로운 노드를 등록하고 전체 네트워크에 알림
app.post('/register-and-broadcast-node',function(req,res){

})
// 네트워크에 새로운 노드 등록
app.post('/register-node',function(req,res){

})
// 새로운 노드에 기존의 노드 정보 등록
app.post('/register-nodes-bulk',function(req,res){

})


npm promise api 설치 - js에서 비동기작업을 순차적으로 or 병렬로 처리가능하게 컨트롤하는 모듈


npm install request-promise --save

npm install request --save


둘다 입력!



promise 에 대한 자세한 설명

http://programmingsummaries.tistory.com/325

모듈 임포트

맨위쪽에 promise 모듈을 사용할 변수 설정

//request-promise 모듈
var rp = require('request-promise');


새로운 노드를 전체 노드에 등록하고 알리는 코드작성

//새로운 노드를 등록하고 전체 네트워크에 알림
app.post('/register-and-broadcast-node',function(req,res){
//새로 진입한 노드 주소
const newNodeUrl = req.body.newNodeUrl;
//비트코인 네트워크에 새로 진입한 노드의 주소가 없을 경우 추가
if(bitcoin.networkNodes.indexOf(newNodeUrl) == -1){
bitcoin.networkNodes.push(newNodeUrl);
}
const regNodesPromises = [];
//비트코인 네트워크에 등록된 네트워크에 새로운 노드 정보를 등록
bitcoin.networkNodes.forEach(networkNodes => {
//register - node
const requestOption = {
uri: networkNodesUrl + '/register-node',
method: 'POST',
body:{newNodeUrl:newNodeUrl},
json:true
};
//순차적으로 비동기를 실행하기 위해서 배열에 넣음
regNodesPromises.push(rp(requestOption))
}); //for 문 끝

//순차적으로 비동기 작업 처리
Promise.all(regNodesPromises)
.then(data => {
//새로운 노드안에 전체 네트워크에 대한 정보 한번에 입력해주기
const bulkRegisterOption = {
uri : newNodeUrl + '/register-nodes-bulk',
method : 'POST',
body : {allNetworkNodes : [...bitcoin.networkNodes,bitcoin.currentNodeUrl]},
json : true
};
return rq(bulkRegisterOption);
}).then(data => {
res.json({nodt: "새로운 노드가 전체 네트워크에 성공적으로 등록이 되었습니다."});

});
});


전체 네트워크에 새로운 노드 등록하는 코드

// 네트워크에 새로운 노드 등록
app.post('/register-node',function(req,res){
//새로운 노드 주소
const newNodeUrl = req.body.newNodeUrl;
//코인 네트워크에 새로운 노드의 주소가 없다면,
const nodeNotAlreadyPresent = bitcoin.networkNodes.indexOf(newNodeUrl) == -1;
//코인의 현재 url이 새로운 노드 주소가 아니라면, 즉 현재 접속한 주소와 중복되지 않는다면,
const notCurrentNode = bitcoin.currentNodeUrl !== newNodeUrl;

if(nodeNotAlreadyPresent&&notCurrentNode){
//코인 전체 네트워크에 새로운 주소 등록
bitcoin.networkNodes.push(newNodeUrl);
res.json({note: "새로운 노드가 등록되었습니다."})
}

})


결과확인

3001-3005번 서버를 다 작동시킨다.

웹브라우저에 https://localhost:3001/blockchain 입력후 확인


postman을 열어서 body로 json 데이터 전송

 

웹브라우저 다시 확인


마무리


다른 주소로도 여러번 테스트 해보자. 다음 포스팅에서 마저 정리하도록 하겠다.



  1. 기웃거리는 개발자 2018.06.14 18:03 신고

    한수 잘 배웠습니다.. 직접 코딩 해봐야 데이터 처리 흐름에 개념이 오네요.ㅎㅎ
    감사합니다~

  2. kebi300 2018.06.29 13:53 신고

    안녕하세요. 덕분에 많은 것을 배우고 가요.

    근데 register-and-broadcast-node 부분은 아직 작동안하는데, 다음 포스트에서 하시나요?

    그리고 forEach 구문에서 networkNodes=> 이 아니라 networkNodesUrl=>

    아닌가요? 오타인듯 해서요.

    좋은 포스팅 감사합니다.


    bitcoin.networkNodes.forEach(networkNodes => {
    //register - node
    const requestOption = {
    uri: networkNodesUrl + '/register-node',
    method: 'POST',
    body:{newNodeUrl:newNodeUrl},
    json:true
    };
    //순차적으로 비동기를 실행하기 위해서 배열에 넣음
    regNodesPromises.push(rp(requestOption))
    })

  3. ㅇㅁㄴ 2018.08.09 16:55 신고

    TREBIT

    코인거래소
    Trebit 이 원화마켓을 오픈합니다 :)
    8월 8일 18시 기준 원화마켓이 오픈이 되었습니다 !

    원화(KRW)마켓 오픈과 함께
    옵저버(OBSR)와 아이온(ION) 8월10일 상장!!!

    특히 옵저버(OBSR)는 전 세계 최초로 트래빗 거래소에 상장되는 코인으로,

    일반 암호화폐와 다르게
    ICO를 진행하지 않고 상장되는 종목입니다.

    원화(KRW)마켓 오픈 기념으로
    거래수수료 0% 이벤트를 진행 중이니
    수수료 부담 없이 거래하시고,
    무려 3억원 상당의
    에어드랍 이벤트의 주인공에 도전해 보세요.

    트래빗고객센터 : 1600-5433
    운영시간 : 평일 09:00 ~ 18:00
    이용문의 : cs@trebit.com

    *옵저버 더 알아보기: http://www.obsr.org/index
    *아이온 더 알아보기: https://ionomy.com/games

  4. 코더 2018.08.28 22:25 신고

    포스팅 정말 감사드립니다 자바스크립트로 코인 만들어보고 싶었는데 이렇게 이해하기 쉽게 올려주셔서ㅜㅜ

자바스크립트로 블록체인 구현 강좌 9 - 나만의 비트코인 발행하기


이번시간에는 api.js에 app.get() , app.post() 부분을 작성해주고, 개발에 조금 더 도움을 줄 node api를 설치 해보도록 하겠다. node js 에서 get, post이 부분이 이해가 안간다면...구글링을 부탁드린다..여기서는 조금이라도 알고 있다고 가정하고 쭉쭉 설명하겠다.


먼저 api.js 소스 코드다

var express = require('express')
var app = express()

// 웹브라우저에 get 방식으로 /blockchain 주소를 입력했을 때 실행
app.get('/blockchain', function (req, res) {
res.send('blockchain Start')
})

// 웹브라우저에 post 방식으로 /transaction 주소를 입력했을 때 실행
app.post('/transaction', function (req, res) {
res.send('transaction Start')
})


// 웹브라우저에 get 방식으로 /mine 주소를 입력했을 때 실행
app.get('/mine', function (req, res) {
res.send('mine Start')
})



app.listen(3000,function(){
console.log('listening on port 3000')
})

위에 소스코드 설명은 express js 기초지식에 해당되므로 여기서는 패스하고 간단하게 주석을 달아놓았다. 

서버 가동

브라우저 확인

nodemoe api 설치

nodemon  은 소스 수정시 자동으로 서버를 재실행시켜주는 api이다. 설치 안해도 무방하나 설치 해놓으면 엄청편하기 때문에 설치한다.

https://www.npmjs.com/package/nodemon

순서

터미널 열고 -> 개발폴더위치 -> npm i nodemon --save 입력 -> package.json 이동 -> script 부분에 아래 문자 추가  "start" : "nodemon --watch dev -e js dev/api.js" 

혹시나해서 나의 package.json 파일 전체를 올린다.

{
"name": "blockchain",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start" : "nodemon --watch dev -e js dev/api.js"
},
"author": "",
"license": "ISC",
"dependencies": {
"express": "^4.16.3",
"nodemon": "^1.17.5",
"sha256": "^0.2.0"
}
}


그리고 다시 터미널 창으로 가서 개발 폴더에 위치하고 서버를 실행한다. 이번에는 npm start 명령으로 실행해보자.

확인 - 아래처럼 출력되면 성공이다.(안되도 크게 상관은 없다. 서버를 수동으로 재시작 해주면되니깐.)


body-parser api 설치

위에서 nodemon을 설치했던것 처럼 터미널 열기 -> 개발 폴더 위치 -> npm i body-parser --save 입력-> 엔터

이 모듈은 express js에서 post방식으로 파라미터를 넘길 수 있게 하는 모듈이다. 쉽게 말하면 웹주소를 이용해서 데이터를 넘기는 것을 도와주는 녀석이라고 생각하면 된다. 암튼 자세한건 구현하면 아~ 하고 이해가 될 것이다. 그리고 api.js 맨위쪽에 var app= express() 이 부분 아래 body paser를 사용하겠다는 코드를 작성해준다.

var express = require('express')
var app = express()
//bodyParser 임포트
var bodyParser = require('body-parser')

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended:false}))



api.js 에서 post transaction 코드 작성

// 웹브라우저에 post 방식으로 /transaction 주소를 입력했을 때 실행
app.post('/transaction', function (req, res) {
console.log(req.body);
res.send(`거래 총액은 ${req.body.amount} 코인`);
})


postman에서 확인 해보기 (https://www.getpostman.com)

포스트맨은 웹상에서 데이터를 웹브라우저 주소로 넘길때 간단하게 테스트 해볼 수 있는 서비스다. 위의 홈페이지로 들어가서 각각 운영체제에 맞는 버젼을 다운로드 하자.


확인

포스트맨에 들어가서 맨위 붉은 줄 처럼 주소를 적고 body를 선택하고 raw , JSON 선택후 아래 문자를 작성한 뒤 Send 를 눌러보자. 그러면 거래 총액은 200 코인 으로 아래 소스 코드로 데이터가 넘어와서 출력된것을 알 수 가 있다.

// 웹브라우저에 post 방식으로 /transaction 주소를 입력했을 때 실행
app.post('/transaction', function (req, res) {
console.log(req.body);
res.send(`거래 총액은 ${req.body.amount} 코인`);
})


app.get /blockchain 작성 

웹브라우저에서 get 방식으로 /blockchain 주소가 들어왔을 경우. bodypaser 모듈을 임포트 하는 코드 아래에 밑의 코드 작성. 

//앞에서 만든 blockchain 모듈 임포트 -> 코인객체 생성
var Blockchain = require('./blockchain');
var bitcoin = new Blockchain();


app.get('blockchain') 부분 코드 작성

// 웹브라우저에 get 방식으로 /blockchain 주소를 입력했을 때 실행
app.get('/blockchain', function (req, res) {
res.send(bitcoin)
})


웹브라우저에서 테스트 - 제네시스 블락 정보가 json 형식으로 뜬다.

/transaction 부분을 담당하는 함수안 내용 수정 - 거래가 발생했을때 새로운 트랜잭션을 생성하기 때문에 발생하는 정보를 console.log 로 찍어주도록 하자.

// 웹브라우저에 post 방식으로 /transaction 주소를 입력했을 때 실행
app.post('/transaction', function (req, res) {

const blockIndex = bitcoin.createNewTransaction(req.body.amount,req.body.sender,req.body.recipient)
res.json({note : `트랜젝션은 ${blockIndex} 블락안으로 들어갈 예정입니다.`})

})



postman으로 확인 - 총 4번의 send를 누름 (4번의 거래 발생)



/blockchain 확인 -  위에서 발생한 트랜잭션 데이터가 pendingTransaction [] 에 들어가 있다. 저건 언제 index 1 블락으로 들어갈까? 이전전전 포스트에서 다뤘다. 새로운 블락이 생성될때. 그건언제인가? 컴퓨팅 파워를 통한 채굴. 마이닝!  그 작업을 통해서 맞는 hash 값을 찾았을 때 새로운 블락이 생성되면서 이전 거래 내역이 새로운 블락안으로 들어간다.  이번 포스팅은 여기서 마무리 하도록 하겠다.



자바스크립트로 블록체인 구현 강좌 8 - 나만의 비트코인 발행하기

이번 포스팅 부터는 앞에서 만든 blockchain을 서버에서 구현해보도록 하겠다. 우리는 서버 구축을 간단하게 도와줄 express api를 사용할것이다. 일단 구글로 가서 express npm을 검색하자. 아래 주소로 들어가도 된다.

https://www.npmjs.com/package/express

콘솔을 열어서 위에 install명령어를 자신의 개발 폴더 위치에서 입력해준다.


이제 express api를 설치 완료 했다. 

개발환경으로 가서 api.js 파일을 생성해주고 아래 소스 코드를 입력해주자 아래 소스코드는 express npm 문서에 있다. 간단하게 설명하면 app.get은 웹브라우저에 / 의 값이 들어오면 함수 아래를 실행하겠다는 뜻이다. /main, /home 등 다양한 주소를 입력해 줄 수 있다. 그러면 이 get 함수가 브라우저에 입력되는 문자열을 확인해서 함수를 실행한다. 

app.listen은 몇번 포트를 설정할것이다 라는뜻 3000이면 localhost:3000으로 입력을 해야 위에 get 함수가 실행이 된다. 설명이 너무 간단하고 추상적인데 이해가 안간다면 구글에 node js epxress 에 관한 기초지식을 쌓고 오는 것도 좋겠다.


var express = require('express')
var app = express()
app.get('/', function (req, res) {
res.send('Hello World')
})
app.listen(3000)


네비게이션



서버실행

이제 터미널을 열고 node 경로/api.js 를 실행시켜준다. 그리고 웹브라우저에 localhost:3000을 입력- > helloworld 출력 확인



마무리

이제 blockchain을 구현할 서버작업을 마쳤다. 앞으로 이 서버가 어떻게 사용이될지 조금더 살펴보겠다.

자바스크립트로 블록체인 구현 강좌5 - 나만의 비트코인 발행하기


이번 포스팅에서는 sha256 해시생성기와 npm을 이용해서 sha256 모듈을 설치해서 사용해보도록하겠다.

일단.

sha256 은 암호화 알고리즘의 하나이다. 음..엄청쉽게 말해서 '어떤 입력값이든 고정된 길이의 임의의 문자열값으로 출력한다' 라고 알고 있으면 쉽다.

예를 들면 abc 값을 sha256 알고리즘에 넣고 돌리면

BA7816BF8F 01CFEA4141 40DE5DAE22 23B00361A3 96177A9CB4 10FF61F200 15AD

이값이 생성이된다. 길이를 보자.

abcdef를 넣으면?

BEF57EC7F5 3A6D40BEB6 40A780A639 C83BC29AC8 A9816F1FC6 C5C6DCD93C 4721

같은 길이의 임의의값이 출력이 된다.

 

https://passwordsgenerator.net/sha256-hash-generator

이곳에 들어가서 직접 값을 넣어봐도 된다.


그리고 한번 암호화 한건 다시 되돌리기 힘들다는 것이다. 어려운 말로 복호화가 어렵다고 하는데 그냥 아 한번 암호화 해버리면 다시 원래 값으로 되돌리기가 거의 빌게이츠가 삼와머니에서 돈빌릴 확률 보다 낮다고만 알아두자.


그러면 계속해서 코드를 작성해보자. 이번에는 인자값을 받으면 그것을 이용해서 암호화 한다음 리턴해주는 함수를 작성해보도록 한다. 


1.구글에서 npm sha256 모듈 검색 후 다운로드 하기

https://www.npmjs.com/package/sha256 여기 들어가면 npm i sha256 --save 이렇게 생긴 녀석을 볼 수 있다


2.터미널 열고 자신의 개발폴더(blockchain)로 가서 위의 명령어를 쳐준다.



3.확인해보기


3.모듈을 변수에 할당

blockchain.js 맨위에 작성

//sha256 모듈을 가져다 쓰겠다.
const sha256 = require('sha256');



4.Blockchain.prototype 함수들 이어서 맨아래 작성

//해쉬 값 리턴 함수
Blockchain.prototype.hashBlock = function(previousBlockHash,currentBlockData,nonce){
const dataAsString = previousBlockHash + nonce.toString() + JSON.stringify(currentBlockData);
const hash = sha256(dataAsString);
return hash
}


다음 포스팅에서 작성한 해쉬함수를 어떻게 사용하는지 테스트 해보도록하자.





자바스크립트로 블록체인 구현 강좌3 - 나만의 비트코인 발행하기



이번포스팅에서는 마지막 블록을 얻는 함수, 새로운거래가 발생할때 거래 트랜잭션 데이터를 생성하는 함수를 만들어 보도록 하겠다.

먼저 blockchain.js 로가서 이어서 코드를 작성해보자.


Blockchain.prototype.createNewBlock  ... 생략. 이 코드 아래에 마지막 블록을 가져오는 함수를 작성한다.


//마지막 블록 얻기 - chain 배열에는 블록데이터가 들어간다. 맨마지막 블록을 가져와라.
Blockchain.prototype.getLastBlock = function(){
return this.chain[this.chain.length - 1];
}


그 밑에 새로운 트랜잭션이 발생했을 때 작동되는 함수를 작성한다.

참고로 거래가 발생할때 마다 생성되는 데이터를 트랜잭션이라고 하는데, 중요한건 트랜잭션은 거래로 인해 발생한 어떤 것이지 블록이 아니다. 블록이 되려면 채굴자들이 마이닝, 즉 컴퓨팅 파워로 채굴을 해야 한다. 그래서 아직 완결이 안된 데이터라고도 할 수 있다. 우리는 맨위에 function Blockchain(){} 데이터 구조에서 this.newTransaction = [] 배열을 생성했다. 이 이름을 좀 더 직관적으로 pendingTransaction으로 바꿔주도록 하자. 아직 대기상태의, 미완결된 값이기 때문에 이렇게 작명을 해주겠다. 전부다 바꿔주도록 하자.

//새로운 트랜젝션(거래)가 발생했을 때 작동되는 함수
//인자값으로, 총액수, 보내는사람, 받는사람이 들어간다.
Blockchain.prototype.createNewTransaction = function(amount,sender,recipient){
const newTransaction = {
amount: amount,
sender: sender,
recipient: recipient
}

//맨위 트랜잭션 배열에 값을 넣어준다.
this.pendingTransaction.push(newTransaction);

//마지막 블록의 index 에서 + 1
return this.getLastBlock()['index'] + 1
}


blockchain.js의 전체 코드는 아래와 같다. 다음 포스팅에서는 test.js에서 이번 포스팅에서 만든 함수들이 어떻게 출력이되는지 찍어보도록 하겠다. 

//블록체인 데이터 구조
function Blockchain(){
this.chain = [];
this.pendingTransaction = [];
}


//블록체인 프로토 타입 함수 정의
Blockchain.prototype.createNewBlock = function(nonce,previousBlockHash,hash){
//새 블록 객체
const newBlock = {
index: this.chain.length + 1,
timestamp: Date.now(),
transactions: this.pendingTransaction,
nonce:nonce,
hash:hash,
previousBlockHash:previousBlockHash
};

//다음 거래를 위한 거래내역 배열 비워주고 새로운 블록을 chin 배열에 추가
this.pendingTransaction = [];
this.chain.push(newBlock);

return newBlock;

}

//마지막 블록 얻기 - chain 배열에는 블록데이터가 들어간다. 맨마지막 블록을 가져와라.
Blockchain.prototype.getLastBlock = function(){
return this.chain[this.chain.length - 1];
}

//새로운 트랜젝션(거래)가 발생했을 때 작동되는 함수
//인자값으로, 총액수, 보내는사람, 받는사람이 들어간다.
Blockchain.prototype.createNewTransaction = function(amount,sender,recipient){
const newTransaction = {
amount: amount,
sender: sender,
recipient: recipient
}

//맨위 트랜잭션 배열에 값을 넣어준다.
this.pendingTransaction.push(newTransaction);

//마지막 블록의 index 에서 + 1
return this.getLastBlock()['index'] + 1
}

//Blockchain 모듈화
module.exports = Blockchain;



자바스크립트로 블록체인 구현 강좌2 - 나만의 비트코인 발행하기


지난 포스팅에서는 자바스크립트로 블록체인 구현을 위한 셋팅과 자바스크립트의 데이터구조와 프로토타입에 대한 기본 지식을 알아보았다. 이번에는 지난번 포스팅에서 구현한 내용을 직접 console.log로 찍어보면서 대충 아~ 이런거구나 하고 감을 잡아보자

blockchain.js  모듈화 하기

//블록체인 데이터 구조
function Blockchain(){
this.chain = [];
this.newTransactions = [];
}


//블록체인 프로토 타입 함수 정의
Blockchain.prototype.createNewBlock = function(nonce,previousBlockHash,hash){
//새 블록 객체
const newBlock = {
index: this.chain.length + 1,
timestamp: Date.now(),
transactions: this.newTransactions,
nonce:nonce,
hash:hash,
previousBlockHash:previousBlockHash
};

//다음 거래를 위한 거래내역 배열 비워주고 새로운 블록을 chin 배열에 추가
this.newTransactions = [];
this.chain.push(newBlock);

return newBlock;

}

//Blockchain 모듈화
module.exports = Blockchain;

module.exports = Blockchain으로 다른 페이지에서도 이 모듈을 사용할 수 있게 해준다.


test.js 로 이동. 

아래와 같이 코드를 작성해준다. 위에서 작성한 블록체인 코드를 여기서 테스트 해보겠다는 뜻이다. 그리고 실행해보자.

//blockchain.js 모듈을 이곳에서 가져다 쓰겠다.
const Blockchain = require('./blockchain')

//위에서 가져온 모듈의 객체를 만든다.
const bitcoin = new Blockchain();

//찍어보기
console.log(bitcoin)


 node 명령어로 실행해보기 

 node 명령어로 실행한거 확인해보기 -  짜쟌


저게 먼지는 아직 잘 몰라도 일단 콘솔에 우리가 적은 코드랑 비스무리한게 떴다.

자 그럼 이제 직접 새로운 블락을 생성해보자

주석으로 새로운 블락 만들기를 보자. createNewBlock은 앞 포스팅에서 만들어놓은 프로토 타입 함수다. 인자값으로 일단 아무 값이나 넣어주었다.

//blockchain.js 모듈을 이곳에서 가져다 쓰겠다.
const Blockchain = require('./blockchain')

//위에서 가져온 모듈의 객체를 만든다.
const bitcoin = new Blockchain();

//새로운 블락 만들기
bitcoin.createNewBlock(1111,"aaaaaaa","1a1a1a1a1a1a");

//찍어보기
console.log(bitcoin)

//결과
//Blockchain { chain: [], newTransactions: [] }


다시 실행해보자


와우. 일단 그럴듯한 객체 데이터가 생성이 된것을 볼 수 있다. 몇개를 더 만들어 볼까?

//새로운 블락 만들기
bitcoin.createNewBlock(1111,"aaaaaaa","1a1a1a1a1a1a");
bitcoin.createNewBlock(2222,"bbbbbbb","2b2b2b2b2b2b");
bitcoin.createNewBlock(3333,"ccccccc","3c3c3c3c3c3c");


결과

Blockchain {

  chain: 

   [ { index: 1,

       timestamp: 1527223987875,

       transactions: [],

       nonce: 1111,

       hash: '1a1a1a1a1a1a',

       previousBlockHash: 'aaaaaaa' },

     { index: 2,

       timestamp: 1527223987875,

       transactions: [],

       nonce: 2222,

       hash: '2b2b2b2b2b2b',

       previousBlockHash: 'bbbbbbb' },

     { index: 3,

       timestamp: 1527223987875,

       transactions: [],

       nonce: 3333,

       hash: '3c3c3c3c3c3c',

       previousBlockHash: 'ccccccc' } ],

  newTransactions: [] }


이번 포스팅에서는 새로운 블락을 생성하고 콘솔로 한번 찍어 보았다. 아직은 이게 먼지 100% 감이 안올거다. 일단 하나씩 따라와 보자. 

  1. 김도원 2018.07.07 12:38 신고

    오타 있네요 ㅎㅎ..

    첫번 째 코드블록 주석 보시면
    //다음 거래를 위한 거래내역 배열 비워주고 새로운 블록을 chin 배열에 추가

    의 주석 중 chin 배열에 추가 인데 chain 배열에 추가 로 변경해야합니다 ~

    • 길위의 개발자 2018.07.09 17:27 신고

      감사합니다. 급하게 정리하느라 검토를 못했습니다. ㅠㅠ 요즘 일이 바빠서 블로그 정리도 못하고 있네요. 더운날씨 건강조심하시기 바랍니다.

2년전부터 블록체인 기술에 관심이 생겨서 이것저것 찾아보면서 지식을 쌓았다. 이론만 공부하면 뜬구름 잡는 이야기처럼 들릴 수 있기 때문에 개발자라면 직접 구현을 한번 해보는것이 중요하다. 블록체인을 구현할 수 있는 언어들이 많지만 그중에서 가장 접근성이 쉬운 자바스크립트를 이용해서 개발을 해보겠다. 일단 자바스크립트와 node .js에 대한 기초 지식은 있어야 한다.


자바스크립트로 블록체인 구현 강좌1 - 나만의 비트코인 발행하기

1.셋팅

바탕화면에 개발 폴더를 만든다. 예를 들면 blockchain폴더를 만들었다고 하자. 그 폴더 위치에서 npm init을 해준다. 그러면 node js 서버를 구축 할 수 있는 기본 셋팅이 완료 된다. blockchain 폴더 안에 dev 폴더를 만들고 그안에 test.js blockchain.js 폴더를 만들자. 아래 그림과 같다.


2. 기초지식 - 자바스크립트 데이터 구조

본격적으로 들어가기전에 자바 스크립트로 데이터를 주고 받을 데이터 구조에 대한 개념을 살펴보자. 일단 데이터 구조는 function 키워드로 만든다. 


function User(name,age){

this.name = name;

this.age = age;

}


이렇게 구조를 만들었으면 이 구조를 이용해서 객체를 생성할 수 있다.


var user1 = new User('길위의 개발자', '30');

....

var user50000 = new User('스티브잡스', '31');


이런식이다. 이렇게 user의 수천 수만건의 name, age 데이터를 컨트롤 할 수 있다.


3.기초지식  - 자바스크립트 프로토타입 객체

프로토타입은 아주 쉽게 말해서 함수에 속성이나 기능을 공통적으로 추가하는 객체를 이야기 한다. 엄청간단하게 말하면 그렇다. 예를 들면

위에서 만든 User 함수에 

User.prototype.emailDomain = "@google.co.kr";

이라고 설정해주면 User 로 만든 모든 객체들이 예를들면 user1....user5000까지 emailDomain 속성을 가지게 되고 그 값으로 @google.co.kr 을 가진다.

user50000.emailDomain; 이라고 쳐보자 위에서 대입한 이메일 값이 나올것이다. 이렇게 속성 값을 공통으로 지정해 줄 수 있을 뿐 아니라 기능도 추가해 줄 수 있다.


User.prototype.getEmailAddress = function(){

return this.name + this.age this.emailDomain;

}

이런식으로!


그리고 

user50000.getEmailAddress(); 라고 쳐보자 어떤 값이 나오는지! 유저 객체의 이름과 나이, 이메일 값을 리턴하는 것을 볼 수 있을 것이다.


3.블록체인 데이터 구조 만들기

위의 내용을 기초로 블록체인 데이터 구조를 만들어 보자. blockchain.js 파일을 열고 아래와같은 코드를 넣어준다.

//블록체인 데이터 구조
function Blockchain(){
this.chain = [];
this.newTransactions = [];
}


클래스를 이용해서 아래처럼 만들 수 있지만 위에 데이터 구조를 이용하겠다.

//클래스를 이용한 블록체인 데이터 구조 위와 동일하다...
class Blockchain{
constructor(){
this.chain = [];
this.newTransactions = [];
}
}


3.블록체인 프로토타입 함수 정의하기

위에서 블록체인 데이터 구조를 정의 했으면 이번에는 프로토 타입 함수를 이용해서 블록체인 객체에 새로운 블록생성 기능을 담당하는 함수를 정의한다. 새로운 블록이 생성될때 발생하는 시간데이터, 순번 데이터, hash 데이터들을 담을 newBlock 객체를 만들어 주었다.

nonce, hash 는 블록체인 이론에 대해서 설명을 해야 되기 때문에 이번 포스팅에서는 넘어가도록 하자. 아직까지 이해가 안갈 수 있는데 나중에 이 함수가 어떻게 출력이 되는지 직접 데이터를 찍어보겠다.

//블록체인 프로토 타입 함수 정의
Blockchain.prototype.createNewBlock = function(nonce,previousBlockHash,hash){
//새 블록 객체
const newBlock = {
index: this.chain.length + 1,
timestamp: Date.now(),
transactions: this.newTransactions,
nonce:nonce,
hash:hash,
previousBlockHash:previousBlockHash
};

//다음 거래를 위한 거래내역 배열 비워주고 새로운 블록을 chin 배열에 추가
this.newTransactions = [];
this.chain.push(newBlock);

return newBlock;

}



여기까지 정리하면 아래 그림과 같다



인터뷰 형식으로 알아보는 블록체인


블록체인 스터디에서 각 팀원들이 주고 받은 내용을 인터뷰 형식으로 정리했습니다.



 돈이란 무엇인가?



- 돈이란 사람들이 필요로 하거나 원하는 가치를 보다 쉽게 저장하고 교환하기 위한 수단이나 매개체라고 생각한다

물물교환의 시공간적 한계를 뛰어넘기 위해 만들어졌고, 가치평가의 기준이 된다. 그리고 돈의 가치는 사람들간의 합의를 통해 부여된다.



 비트코인이 돈의 위치까지 올라갈 수 있는가?



비트코인을 포함한 모든 탈중앙화 기반의 화폐가, 기득권(중앙기관) 인정하는 화폐의 가치를 위협할수있기때문에 당연히 좋아하진 않을것같습니다 



지금은 양적완화라는 이름으로 화폐를 발행하고 있는데, 이는 비트코인과 별반 다르지 않은 모습니다. 제도권에서 통제가 가능하나 안하냐가 중요한 이유가 되고 있다고 생각합니다.



다른 관점에서, 보통 정책이 기술의 속도를 따라가기 때문에 정부 정책이 보조를 맞춰준다면 어느정도 상용화되지 않을까 합니다. 저가형 스마트폰도 개발도상국에 많이 보급이 된다면 사용자도 늘어날 같다는 생각이 드네요.




기존의 돈과 비트코인은 어떻게 다른가?


- 돈은 중앙은행의 통제하에 있지만, 비트코인은 채굴자들(누구나 참여가능) 통하여 발행할수 있고, 이는 생태계에 보안에 간접적으로 기여하여 시스템을 유지하게 됩니다.



-기존의 돈은 거래 당사자간의 거래의 방식, 화폐를 중앙 기관(주로 국가 은행) 보증함. 비트코인의 경우 네트워크에 참여한 어떤 사람이라도 화폐(비트코인 거래의 기록) 내용을 가지며, 이를 신뢰할수 있음.



-기존의 돈과 비트코인의 다른점 하나는 돈의 사용이나 이동은 3신뢰기관의 서버에 기록이 되고, 비트코인은 모든 사용자들의 서버에 즉시 기록이 된다는 점이라고 생각합니다.



-거대 채굴풀이나 고래들에 의해서 발행량 유동성 가격이 좌우된다면 기존 돈과 다른 점은 무엇인가요? 주체만 은행이나 정부기관에서 바뀐건 아닌지요? 오히려 이렇게 경우에는 규제나 도덕선 없이 자본으로만 움직이는 주체들 그것도 익명의 주체들에게 너무 권한이 이양되는건 아닌지 걱정이 됩니다.



스마트 컨트랙트란 무엇인가?



- 블록체인 기반으로 금융거래 부동산 계약 공증 다양한 계약을 체결하고 이행하는 것을 말하고 이를 계기로 블록체인 2.0이라 한다. 조건문인 if then 문구를 넣으면 조건이 받아들여지면 자동으로 계약이 체결되게끔 하는 시스템.


- 토큰의 소스코드에 어떤 조건문이 들어가 있기 때문에 조건을 만족하는 계약이라면 즉시, 해당 계약이 체결되고, 내용이 블록체인에 기록되어 영구적으로 보관되는 것을 말한다. 따라서 계약자들이 신뢰할 있고, 일방적으로 계약을 파기하거나 계약 사항에 맞지 않는 거래는 일어나지 않는다.


- 블럭체인 내에 계약조건은 포함하도록 하여, 조건에 만족하면 이행되더록하는



- 사용자가 컨트랙트 코드에 버그가 있고, 수행후 롤백이 안된다면 부작용이 많이 일어날거라는 막연한 생각을 해봤어요.부동산 계약서도 계약문구를 정확이 이해하지 못하고 사기당하는 경우가 많은것처럼, 스마트콘트랙트도 코드를 이해못하면 사기당하는경우가 나올것같네요



-  아래와같은 스마트컨트랙트가 있다고가정해봅시다

#내일 날씨가 섭씨 5도보다 낮으면 A B에게 1만원을


그럼 이상황에서 과연 내일 온도가 몇도인지는 누가 알려줄것이며, 정보가 정확한지는 누가 판단할것인가? 주고, 높으면 B A에게 1만원을 준다


이게 일명 오라클 문제라고 불리는 문제이며, 결국 현실세계에서 데이터를 가져와야하는데 현실세계 데이터의 신뢰성은 누가 보증하냐는 문제입니다.


https://steemit.com/oracle/@energist/blockchain-study-oracle





블록체인 기술로 어떤 분야를 혁신할 있을 같은가?


특허분야를 혁신할 있을 같다. 현재는 어떤 기술을 갖고 특허를 받기 위해서는 국가의 특허청마다 출원을 하여 심사를 받고 등록이 되는 시스템이다. 따라서 같은 기술이라도 어느 국가에서는 등록이 되고, 어떤 국가에서는 심사에서 탈락하여 등록이 되지 않는 경우도 발생한다. 만약 국제적으로 합의된 토큰을 이용한다면 심사 통과 즉시 내용이 블록체인에 등록되고, 모든 국가에서 사항을 확인할 있게 것이다. 따라서 특허자는 특허권을 안전하게 보유할 있고 국가에서 특허의 선후관계로 발생할 있는 특허소송과 그에 따른 비용도 줄일 있을 것이다. 외에도, 논문의 피인용지수와 비슷한 개념을 도입하여 인용된 횟수 만큼 인용자로부터 토큰을 지급받을 있다면, 특허 소유자는 유용하게 이용되는 특허에 대해 합당한 보상을 받을 있을 것이다.




해외송금 분야에서 Swift 대체

: 리플로 대체하고 있음. Swift 망을 씀으로써 발행하는 수수료를 블록체인으로 대체하여 비용은 낮추고 처리시간은 빠르며 투명하게 제공이 가능함

소액주주의 주총 참여가능 : 소액주주들에 소유 지분 만큼 블럭체인을 통해서 주주총회에 참여함으로써 최근 이슈화 되고 있는 재벌가문제를 일정 부분 해결할 있다고 생각함






'경제 > 블록체인' 카테고리의 다른 글

블록체인 기초 정리2  (0) 2018.05.25
블록체인 기초 정리  (0) 2018.05.25
인터뷰 형식으로 알아보는 블록체인  (0) 2018.05.14
키워드로 알아보는 블록체인 정리  (0) 2018.05.14

+ Recent posts

티스토리 툴바