Blockchain

#17 ethereum

Sila 2022. 6. 29. 20:46

#16까지 알아본 블록체인과 tx는 최초의 암호화폐인 비트코인의 작동방식이었다.

 

이 후에 나온 이더리움은 비트코인과는 다른 용도로 만들어졌다.

 

비트코인은 가치의 저장 수단으로서 만들어진 이른바 디지털 금이라면,

 

이더리움은 네트워크에서 화폐의 지불과 송금뿐 아니라 스마트 컨트렉트 등,

 

사용자들이 블록체인 네트워크 상에서 

 

가장 단순하게 A가 B에게 돈을 주되 특정한 조건이 만족되어야만 돈이 B에게 전달된다던지 등

 

단순히 돈을 주고 받는 것 이외에 계약이라는 것을 구현할수 있게끔 설계된 디지털 석유라고 볼 수 있다.

 

우리들의 먼 목표는 이 이더리움이라는 플랫폼 안에서 스마트 컨트랙트를 구현하는 것이지만 우선

 

이더리움 네트워크를 사용하는 기본적인 방법과 라이브러리, 프로그램부터 알아가자.

 

1. Go ethereum (geth)

geth는 이더리움 블록체인 네트워크 상에서 구동할  dApp개발에 도움을 주기 위한 만든 오픈소스 툴이다.

 

실제로 구동중인 이더리움 메인넷을 사용할 경우, 테스트마다 실제로 이더리움을 소비해야하기 때문에

 

geth이 제공해주는 테스트넷을 이용함으로써 경제적인 소모없이 개발을 진행할 수 있다.

 

geth는 wsl 환경에서 설치한다.

 

sudo apt update
sudo apt install golang

sudo apt i -y libgmp3-dev tree make build-essential

 

설치가 되면 geth를 clone해올 폴더를 하나 만든다. (e.g. mkdir ethereum)

 

git clone https://github.com/ethereum/go-ethereum

cd go-ethereum
make geth

 

혹시 이런저런 오류가 있고, 이를 해결하려고 시도해도 실패했을 경우 그냥 전부 지우고 다시 깔면 해결되었다.

 

여기까지 성공했다면

 

./geth version

 

를 입력해 버전을 확인한 후, (1.18 이후 버전 권장) 루트 디렉토리로 나온 후, 환경 변수를 설정해줄건데

 

(터미널에 geth를 입력하면 바로 geth를 실행하도록)

 

sudo vi ./.profile

 

를 입력해 문서 하단에

export PATH=$PATH:/mnt/c/Users/Lee Seung Jun/blockchain5/work/class/blockchain/0627/ethereum/go-ethereum/build/bin

 

를 입력한 후 저장한다.

 

2. ganache-cli

마찬가지로 이더리움 dApp 개발에 활용할 수 있는 PC에 설치해 사용하는 테스트용 블록체인이다.

 

wsl에서 ganache-cli를 입력하고 실행하면

 

테스트를 해볼 수 있도록 100개의 eth가 있는 지갑 10개를 개인키와 함께 생성해준다.

 

npm i -g ganache-cli

 

ganache-cli를 실행한 상태로 여러 가지 method를 사용해볼 수 있다.

 

지갑을 가져오는 method는 eth_accounts 인데, 이를 req.body에 담아 요청을 보내면 현재 ganache 상에 존재하는

 

지갑에 대한 정보를 모두 보내준다.

 

 

비슷한 방법으로 원하는 지갑의 잔액을 보고 싶다면 지갑 주소와 함께 eth_getBalance method를 사용하면 된다.

 

 

잔액을 알고 싶은 지갑 주소를 params의 배열 안에 넣어주면 해당 지갑의 잔액을 result로 보내준다. (16진수)

 

앞에 0x를 제외한 16진수를 10진수로 바꾸면 10000000000000000000 인데, 100이 아닌 10000000000000000000이

 

나오는 이유는 다른 단위를 사용해 표현했기 때문에 그렇다.

 

3. web3

방금 본 지갑 주소 찾기, 잔액 확인등의 기능을 조금 더 간편하게 해줄 수 있는 라이브러리가 web3 이다.

 

여기서는 web3의 자주 사용하는 기능 몇 가지를 써보고 테스트 해보자.

 

jest를 설치해준다.

 

npm i web3
npm i -D jest

 

jest.config.js를 설치해 다음과 같이 설정해준다.

 

/*  jest.config.js  */

const config = {
    verbose : true,
    testMatch : ['<rootDir>/**/*.test.js']
}

module.exports = config

 

그리고 tx에 대해 도움을 줄 라이브러리 ethereumjs-tx를 설치한다.

 

npm i ethereumjs-tx

 

본격적으로 web3를 이용해 ganache의 블록체인에 web3로 다양한 기능을 시험해보자.

 

/*  web3.test.js  */

const Web3 = require('web3')
const ethTx = require('ethereumjs-tx').Transaction

describe('web3', () => {
    let web3
    
    let accounts
    let sender
    let receiver
    
    it('web3 test', () => {
        web3 = new Web3(new Web3.providers.HttpProvider('http://127.0.0.1:8545'))
    })
    // 요청을 보낼 uri 설정
    
    it('최신 블럭 높이 가져오기', async () => {
        const latestBlock = await web3.eth.getBlockNumber()
        console.log(latestBlock)
    })
    // 결과값 : 0
    
    it('체인의 전체 account 가져오기', async() => {
        accounts = await web3.eth.getAccounts()
        // ganache가 생성해준 10개의 지갑주소를 배열로 가져온다
        console.log(accounts)
        
        sender = accounts[0]
        receiver = accounts[1]
        // 생성된 지갑 중 1번째 지갑에서 2번째 지갑으로 돈을 보내보자
    })
    // 결과값 : [지갑 주소 10개를 가진 배열]
    
    it( '지갑 잔액 확인', async() => {
        const balance = await web3.eth.getBalance(accounts[0])
        console.log(balance)
        // 이렇게 잔액을 출력하면 10^18이 나오는데,
        // 이는 단위를 GWei로 사용하고 있기 때문이다.
        // ether 단위로 바꾸려면 10^18로 나누면 된다
        console.log('ETH : ', balance / 10**18)
    })
    // 결과값 : 100000000000000000000, ETH : 100
    
    it('eth 단위 변경 함수') {
        // 잔액을 표현하는데는 여러가지 단위가 있다.
        // web3를 이용해 그 중 대표적인 몇가지로 단위를 바꿔 출력해보자.
        console.log(web3.utils.toWei('1', 'gwei'))
        console.log(web3.utils.toWei('1', 'ether'))
    })
    // 결과값 : 1000000000, 1000000000000000000
    
    it ('tx 횟수 구하기', async () => {
        const txCount = await web3.eth.getTransactionCount(sender)
        console.log(TxCount)
        console.log(web3.utils.toHex(txCount))
        // 원하는 지갑을 입력하면 해당 지갑이 지금까지 몇 번의 tx를 발생시켰는지도
        // 확인할 수 있다.
    })
    // 결과값 : 0
})

 

결과값이 잘 나왔다면 tx도 한 번 만들어보자.

 

// ...이어서

it('tx 실행', async () -> {
    const txCount = await web3.eth.getTransactionCount(sender)
    
    const privateKey = Buffer.from('bc8372d4a065e257f87fd28e76851cbc621bc6913eee733184efe98687810068', 'hex')
    // 생성해준 10개 개인키 중 첫 번째 개인키를 0x만 떼고 입력한다
    
    const txObject = {
        nonce : web3.utils.toHex(txCount),
        from : sender, // 발신인
        to : receiver, // 수신인
        value : web3.utils.toHex(web3.utils.toWei('1','ether')), // 출금액
        gasLimit : web3.utils.toHex(6721975),
        // ganache 실행시 gasLimit값이 주어진다
        gasPrice : web3.utils.toHex(web3.utils.toWei('1','gwei')),
        data : web3.utils.toHex('')
    }
    
    const tx = new ethTx(txObject)
    tx.sign(privateKey)
    
    const serializedTx = tx.serialize()
    console.log(serializedTx.toString('hex'))
    //
    const txHash = await web3.eth.sendSignedTransaction('0x' + serialized.toString('hex'))
    // tx를 발생시킴
    console.log(txHash)
    // tx 객체의 정보 (가스비 등이 출력 됨)
    
})

/*
    결과값 : {
      transactionHash: '0x5a0f30d4ce4186367faa90e90592b59d9e7f651a69ffa06c75f2946816a68a18',
      transactionIndex: 0,
      blockHash: '0xdc80d3163e43317b3739b4e72ffd34eaeec9f731274b6c46667d857e58342ac4',      blockNumber: 1,
      from: '0x3a461ef4fd5ce55034ab4207f4edff8db4732c69',
      to: '0x9426ca1ccf9eaed55337e3cb9536fdc74159faa8',
      gasUsed: 21004,
      cumulativeGasUsed: 21004,
      contractAddress: null,
      logs: [],
      status: true,
      logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'
    }
*/

it('balance 확인', async() => {
    const senderBalance = await web3.eth.getBalance(sender)
    const receiverBalance = await web3.eth.getBalance(receiver)
    
    console.log('sender balance (eth)' : senderBalance / 10 ** 18 )
    console.log('receiver balance (eth)' : receiverBalance / 10 ** 18 )
    // tx 발생후 발신인과 수신인의 잔고 확인
})

/* 
    - 결과값
    sender balance (eth) :  98.999978996 // = 100 - 출금액 - 가스비
    receiver balance (eth):  101 // 100 + 입금액
    
    가스비는 tx를 발생시키는 쪽이 지불한다
*/

 

4. metamask

이는 브라우저에 추가하는 확장 프로그램이다.

 

개인키는 내 컴퓨터에만 저장하고,

 

메타마스크는 이를 읽어 네트워크 선택, tx에 필요한 공개키, 지갑 주소, 서명 생성등에 대한

 

작업을 알아서 처리해준다.

 

메타마스크를 처음 설치해 실행하면 디폴트로 사용하는 네트워크는 이더리움의 메인 네트워크이다.

 

내가 테스트용으로 사용할 네트워크를 등록해보자.

 

네트워크 (초록 사각형) 을 클릭하고 네트워크 추가를 클릭하면 새로운 창에서 네트워크 추카 페이지가 열린다.

 

이를 다음과 같이 채워주고 저장하면 된다.

 

 

ganache-cli 네트워크의 디폴트 체인 Id는 1337이다.

 

이렇게 이더리움 기반 dApp 개발을 위해 필요한 툴들과 그 기본적인 사용법과 기능을 알아보았다.

 

다음 글에서는 프론트 서버에서 메타마스크와 상호작용하고, 메타마스크를 통해 원하는 블록체인 네트워크와

 

상호작용하는 것을 배워보도록 하자.

'Blockchain' 카테고리의 다른 글

#19 geth  (0) 2022.06.30
#18 metamask 활용  (0) 2022.06.29
#16 transaction ch.6 - tx pool  (0) 2022.06.27
#15 transaction ch.5 - utxo update  (0) 2022.06.27
#14 transaction ch4. - transaction  (0) 2022.06.24