2023.07.26 해커톤 대비 스마트 컨트랙트 맛보기

이무헌·2023년 7월 26일
0

blcokchain

목록 보기
1/10

1.초기 세팅

기본적으로 맥북의 terminal로 세팅을 하였다.
brew를 설치했으니 brew로 진행을 하자. 예를들어

sudo apt update

이런 코드가 있다면

brew update

이렇게 바뀐다. apt가 brew로 대체된다

1.go 언어 설치

$ brew update
$ brew install golang

우리는 geth를 사용할 것이다. geth란?

"Geth"는 Go Ethereum의 줄임말로, Ethereum 네트워크와 상호작용하기 위한 명령줄 인터페이스(CLI)입니다. 이는 Go라는 언어로 작성되었습니다. Geth를 사용하면 개인 네트워크를 생성하거나 기존 Ethereum 네트워크에 연결할 수 있습니다. 또한 스마트 계약을 배포하고 실행하거나 Ether를 전송하는 등의 작업을 수행할 수 있습니다.
Geth는 블록체인 애플리케이션을 개발하는 데 유용한 도구로, Ethereum 블록체인의 기능을 완전히 활용할 수 있도록 해줍니다. 이는 Ethereum 노드를 로컬 머신에서 실행하고, 이를 통해 Ethereum 네트워크에 직접 접근하게 해줍니다. 이러한 기능 덕분에 Geth는 Ethereum 생태계에서 중요한 부분을 차지하고 있습니다.
출처:chatGPT

private 네트워크를 만들어 기존 이더리움 네트워크에 연결하거나 스마트 컨트랙트를 배포할 수 있게 도와줄 수 있는 tool이다.
그러기 위해 go language가 필요해서 설치를 해준 것이다.

geth실행을 위해 추가 파일을 추가한다.

brew install -y libgmp3-dev tree make build-essential

오류가 뜬다면 -y를 제거하자

만약 1.4이하의 버전이라면 git을 이용해서 버전을 업데이트 해주자

git clone https://github.com/udhos/update-golang
 cd update-golang
 sudo ./update-golang.sh

2.이더리움 폴더 생성후 go-ethereum설치

$ cd ~
$ mkdir Ethereum
$ cd Ethereum
$ git clone https://github.com/ethereum/go-ethereum

Ethereum폴더 안에 go-ehtereum을 설치하자
완료가 됐다면 go-ethereum 안에 들어가서 make geth 명령어로 geth를 설치하자.

$ cd go-ethereum
$ make geth

끝났다면 geth명령어를 실행시켜 geth를 실행시켜 보자

$ cd go-ethereum
$ cd ./build/bin
$ # 버전 확인
$ ./geth version
$ # geth 실행 (./build/bin 디렉토리 안에서)
$ ./geth

앗 왜 bin으로 들어가시는 거죠?
geth 명령어는 bin 폴더에서 실행시켜야 한다!
이게 귀찮다면 간단하게 환경변수를 바꿔주자

pwd

pwd로 bin의 현재경로를 찾고

$ vi ~/.bash_profile
$ # 편집
export PATH=$PATH:/home/bitkunst/geth/go-ethereum/build/bin
$ # wq! 저장 후 종료하기
$ source ~/.bash_profile

이제 geth를 실행시키면?


와!
Looking for peers 가 뜬다면 성공이다.이는 연결할 노드를 찾고있다는 말이다. 새로 연결된 노드에서 발생하는 네트워크 데이터들은 로컬에 다운받게된다.

이렇게 geth로 메인넷에 연결할 때마다 블록의 정보를 받는 과정을 동기화라고 한다. geth에는 3가지의 동기화 방법이 있다.

full sync : 모든 블록 정보를 동기화 한다.
fast sync : 블록 헤더 정보를 동기화 하고, 블록 바디는 latest tx 기준 -1024개의 트랜잭션 데이터만 동기화 해주는 작업이다.
light sync : 블록 헤더 정보는 마찬가지로 동기화 하고 latest snapshot만을 동기화한다.
우리는 light sync를 사용하자

geth --syncmode light

3.private network 구축하기

근데 이상한 것이 있다. 왜 chainID가 처음에 1이지??
chainID가 1일 경우엔 mainnet으로 취급되므로 배포가 불가능하다.
바꿔주자
아까 프라이벳 네트워크를 개설했다 하였는데 이 네트워크에서 우리는 블록을 생성할 것이다. 첫 블록! genesis.json으로 만들 수 있다.

{
    "difficulty": "200000",
    "gasLimit": "3100000",
    "alloc": {
        "0xe7Cfd36ACfB1109Ac1080c30Ee7a2FAC263cAAe2": {
            "balance": "100100000000000000000"
        }
    },
    "config": {
        "chainId": 7722,
        "homesteadBlock": 0,
        "eip150Block": 0,
        "eip155Block": 0,
        "eip158Block": 0
    }
}

그 후에 블록체인 데이터가 저장 될 node를 생성함과 동시에 genesis.json으로 초기화 시켜주자

geth --datadir node init genesis.json

--datadir은 이 곳에서 블록체인의 데이터를 처리하고 읽겠다는 옵션이다

생성이 됐다면 실행시키자

geth --datadir node

버그 리포트

계속해서 chainID가 바뀌지 않는 버그가 발생했다. 찾아본 결과
최신 버전(1.12)에서는 더이상 POW방식의 private network구축을 지원하지 않는다고 한다. 즉, POS방식으로 구축을 해야하기 때문에 아무리 chainID를 바꾸려해도 바뀌지 않았던 것이다.
다운 그레이드를 하면 해결된다.

4.transaction test

geth attach http://127.0.0.1:9000

geth를 자바 스크립트로 컴파일이 가능하게 해주는 콘솔을 여는 명령어다.
코인을 받을 계정을 생성하자

person.newAccount( ) 

그 후 10 이더리움을 전송하자

personal.sendTransaction({from: eth.coinbase, to: '54d550ef9da97e38d05fa0589414737e305a6b36', value: web3.toWei(10, 'ether')}

그렇게 되면 해당 트랜잭션 주소가 나타다고
그 후 txpool명령어를 입력하면

txpool

pending 형태로 나타난다.
즉, 블록을 생성할 준비가 되어있다는 뜻이다.

miner.start(8) //8개의 코어 사용한다는 뜻, 겨울에 하면 따뜻해진다.

채굴을 시작하고 조금 기다렸다가

miner.stop()

중단하고 txpool을 실행하면 pending이 비어있다는 것이 확인된다.

그럼 이제 이 주소로 트랜잭션을 확인하자

eth.getTransactionReceipt('0xd69e8d5902f2d63e83c39eaf161eff9a286b98f57e4bbcd35fa24d203422945f')

가스부터 보내는사람과 받는 사람의 주소 등등이 표시되어있다.

5.스마트 컨트랙트 배포


다음과 같이 폴더를 생성하고

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17; // 버전

// HelloWorld 컨트랙트
contract HelloWorld {
    string text;
    constructor(){
        text = "Hello World!";
    }

    function getText() public view returns(string memory) {
        return text;
    }
    function setText(string memory value) public {
        text = value;
    }
}

사진처럼 HelloWorld.sol을 생성하자.

npx solc --bin --abi Contracts/HelloWorld.sol

로 bin파일과 abi파일로 sol파일을 인코딩 하자.

다시 geth 콘솔로 와서

bytecode= '0x <bin파일 복붙>'

abi=<abi파일 복붙>

순으로 변수를 생성하자

txObject={from: eth.coinbase, data: bytecode}

로 새로운 객체를 생성한다.

eth.sendTransaction(txObject)

시원하게 보내자.

엥 ? to가 없는데?

  • 상관없다! smart contract는 EOA가 그저 명령을 주면 안의 메소드를 실행하는 역할이므로 굳이 to가 필요없다.
  • 하지만 unlock되지 않았으므로 geth --allow-insecure-unlock 로 네트워크를 실행하고!(콘솔이 아니라 노드를 받는 geth 네트워크를 위 옵션을 붙인다음, 다시 실행해야한다. )
  • 그 후 콘솔로 다시 돌아와 personal.unlockAccount(eth.coinbase, '1234', 300)
    로 잠시 언락을 하자
contract=eth.contract(abi)

getTransactionReceipt로 가져온 데이터에 contractAddress를 찾아보자. 이는 현재 트랜잭션에 있는 스마트 컨트랙트를 찾을 수 있는 CA다.
이를 contract객체의 at키에 매개변수로 CA를 주자

instance=contract.at(CA)
instance.getText.call()
//Hello World!!

배포가 끝났다!

느낀점
사실 chainID가 바뀌지 않아 많이 골치 아팠다... 다운그레이드로 코드를 해결한적은 이번이 처음이다. 많은 개발자 사이트에서 버전관련해서 많은 오류가 있다고 말은 했지만 실제로 경험해보니 어떨떨하였다. 지금까지는 버전을 자동으로 관리해주는(gradle) 툴을 사용하다. 수동으로 맞춰야 하니 디버깅의 길은 멀고도 험함을 다시 한 번 상기했다.
또한 블록체인의 기본 원리를 좀더 공부해야한다. 주소의 개념과 트랜잭션사이의 관계를 명확히 알아야, 실무에서 새로운 기술을 도입할 때 많은 도움이 될 것이다.

profile
개발당시에 직면한 이슈를 정리하는 곳

0개의 댓글