반응형
해당 글은
- 인프런의 '블록체인과 솔리디티' 강의
- '쉽게 설명하는 블록체인: 머클트리(Merkle Trees) - 뱅크샐러드' https://banksalad.com/contents/%EC%89%BD%EA%B2%8C-%EC%84%A4%EB%AA%85%ED%95%98%EB%8A%94-%EB%B8%94%EB%A1%9D%EC%B2%B4%EC%9D%B8-%EB%A8%B8%ED%81%B4%ED%8A%B8%EB%A6%AC-Merkle-Trees-%EB%9E%80-ilULl
를 참고로 작성되었습니다.
오류사항이 있더라도 너그러히 이해해 주세요!
Blockchain
블록체인?
블록체인은 신뢰를 위해 설계된것! (효율성이 아니다!)
전자 결제, 디지털 인증, 화물 추적, P2P 대출, 식자재 유통 과정, 전자투표, 전자시민권, 부동산 등기부, 병원간 의료기록 관리처럼 투명성과 신뢰성이 요구되는 다양한 분야에 우선 도입 유망
블록 : 데이터 집합
- 예 : a가 b에게 송금한 기록, c가 d에게 송금한 기록을 한데 모아 블록이 됨.
그 블록들을 하나하나 연결한것이 블록체인.
- 그 블록 체인들은 사용자 각각이 가져감.
- 모두 같은 로그를 가지고 있기에 누군가 다른 로그를 가져간다면, 잘못된 정보를 가지고 있다는 것이 증명됨.
- 즉 많은 사람이 접근해야 더 신뢰를 가질 수 있음.
- 그리고 이를 가능하게 하는 것이 암호학
블록체인과 암호학
머클트리(이진트리)
- 머클이라는 사람이 만든 트리구조
- 해싱을 이용한 데이터 검증을 하는 트리구조
'쉽게 설명하는 블록체인: 머클트리(Merkle Trees) - 뱅크샐러드' 캡처
- 두개씩 거래로 묶은 다음 SHA256 알고리즘을 통해 해시값으로 나타냄.
- 이렇게 묶은 값들을 다시 두개로 묶어 또 해싱하여 수백개의 거랩 값들을 그림의 가장 꼭대기 위치한 하나의 데이터로 만들어 주는 것
- 거래가 몇 천개든 뭉쳐 요약된 머클트리의 용량은 32비트로 항상 같다.
- 이진트리이기 때문에 검색 속도는 Log2(N)
- 만일 1024거래일 경우, log2[1024] = 10 이므로 10번의 경로 만으로도 특정거래 데이터를 찾을 수 있다.
- 따라서 , 특정거래 데이터를 쉽게 찾을 수 있고, 트리경로를 따라가면 해시값이 다른것이 나오게 되어 거래의 위변조도 쉽고 빠르게 찾을 수 있다.
- 라이트 노드(light node) : 블록데이터의 일부만 다운 받는 형태. 모바일로도 쉽게 특정 거래를 찾도록 해줌.
블록체인 문제점
1.프라이버시
- 데이터조작 불가. 평생 기록이 남음
2.트랜잭션 코스트
3.트랜잭션 스피드
4.블록사이즈
솔리디티
튜링완전
- 어떤 프로그래밍 언어나 추상머신이 튜링 머신과 동일한 계산 능력을 가진다는 의미.
- 튜링 머신으로 풀수 있는 문제, 즉 계산적인 문제를 그 프로그래밍 언어나 추상머신으로 풀 수 있다는 의미
- msg.sender : 메세이를 보낼 주소
- msg.value : 메세지 보낼 값
스마트컨트랙트
- 이더리움 스마트 컨트랙트 예시
// 1. 컨트랙트 선언
contract Sample {
// 2. 상태 변수 선언
uint256 data;
address owner;
// 3. 이벤트 정의
event logData(uint256 dataToLog);
// 4. 함수 변경자 정의
modifier onlyOwner() {
if(msg.sender != owner) revert();
_;
}
// 5. 생성자
function Sample(uint256 initData, address initOwner) {
data = initData;
onwer = initOwner;
}
// 6. 함수(메소드) 정의
function getData() returns (uint256 returned) {
return data;
}
function setData(uint256 newData) onlyOwner {
logData(newData);
data = newData;
}
}
데이터 타입
contract Sample {
string public myString = "wow"; // utf8
bytes12 public myRawString = "wowowo";
}
맵핑 (key:value 쌍)
contract Sample {
mapping (address => string) myMap;
constructor(string value) public {
myMap[msg.sender] = value;
}
}
- 동적 배열, 정적 배열 모두 사용 가능
contract Sample {
uint[] myDynamicArray = [0, 0];
uint[3] myStaticArray = [1,1,0];
}
- 인터페이스를 사용하여 추상 계층을 사용할 수 있음
interface Token {
function transfer(address recipient, uint amount) external;
}
modifier 한정자 선언
- 함수를 실행시키는 조건으로 사용할 수 있음
- 함수를 실행시키기 전과 실행시킨 후에 특정한 기능을 할 수 있도록 만들 수 있음.
contract Sample {
address owner;
modifier onlyOnwer {
require(msg.sender == owner);
_;
}
funciton ownerCanDoIt(string something) public onlyOnwer view returns (string) {
return something;
}
}
데이터위치
- storage : 상태변수, 로컬변수 (전역변수와 같음, 블로체인 내에 저장됨)
- memory : 로컬변수(사용 후 휘발됨)
솔리디티 문법
- if, else, while, for, break, continue, return, ? :
가시성
- 누가 접근할 수 있는가 (접근 한정자)
external
- 다른 컨트렉트나 트랜젝션에서 호출 가능
- f() ✖︎ , this.f() ✓
public
- 모든 방법으로 접근 가능
internal
- 내부적으로만 접근 가능
private
- internal과 비슷하지만, 상속된 컨트렉트에서는 접근 불가
가스
- evm 에서 뭔가 실행시 가스라는것이 발생됨
- 쉽게 말해 수수료라 생각하면 됨
가스리밋
- 수수료의 한계치
- 낮게 설정시 일을 끝마치기전에 수수료를 다 써버림
- 이럴 경우 이더리움에서는 지금까지한 일을 모두 취소 시키고, 지금까지 사용한 수수료는 돌려주지 않음
- 채굴자들이 일을 했기에 돌려주지 않는것
가스 프라이스
가스당 가격
비싸지면 채굴자들은 수수료를 많이 받을 수 있음
따라서 비싼 가스프라이스가 먼저 채굴되는 경향이 있음
가스프라이스 * 가스사용량 = 수수료
솔리디티에서 가스를 사용할 때마다 가스를 사용하므로 신중하게 스마트 컨트랙트를 짜야함
투표용 이더리움 컨트랙트 만들기
- http://remix.ethereum.org 접속
- 디버깅, 컴파일러 등의 모듈을 추가해야 가능
- 오토컴파일 설정
- 자바스크립트 vm 을 쓰고, 작성한 컨트랙트를 선택하여 Deploy 함.
- 또한 어카운트를 바꿔 실행 해 볼 수 있음.
- 배포 됐다면, 만들어진 함수에 값을 넣거 나 하영 사용하면 된다.
- 디버깅화면도 제공한다.
코드 예
// 어떤버전의 솔리디티를 쓸건지
pragma solidity >=0.4.24 < 0.6.0;
// 컨트렉트 작성
contract Vote {
// strutcure
struct candidator {
string name;
uint upVote;
}
// variable (get candidator 후보자를 확인)
candidator[] public candidatorList;
bool live;
address owner;
// mapping
mapping(address => bool) Voted;
// event
event AddCandidator(string name);
event UpVote(string candidator, uint UpVote);
event FinishVote(bool live);
event Voting(address owner);
// modifier 컨트랙트를 만든 사람만 투표를 끝낼 수 있도록 | 컨트랙트를 만든 사람만 후보자 등록 할 수 있도록
modifier onlyOwner {
require(msg.sender == owner);
_;
}
// constructor
constructor() public {
owner = msg.sender;
live = true;
emit Voting(owner);
}
//기능 정의
// candidator 후보자
function addCandidator(string memory _name) public onlyOwner { // 컨트랙트를 만든 사람만 후보자 등록 할 수 있도록(onlyOwner)
require(live == true);
require(candidatorList.length < 5); // candidatorList.length 가 5보다 작아야지 아래 함수로 내려감. 가스 조절을 위해 필요함
candidatorList.push(candidator(_name, 0));
// emit event
emit AddCandidator(_name);
}
//voting 투표
function upVote(uint _indexOfCandidator) public {
// 이미 투표를 한사람은 제외 시키기
require(live == true);
require(Voted[msg.sender] == false);
candidatorList[_indexOfCandidator].upVote++;
Voted[msg.sender] = true;
candidator memory tmpCd = candidatorList[_indexOfCandidator];
// emit event
emit UpVote(tmpCd.name, tmpCd.upVote);
}
// finish vote 투표끝내기. 컨트랙트를 만든 사람만 투표를 끝낼 수 있도록(onlyOwner)
function finishVote() public onlyOwner {
require(live == true);
live = false;
emit FinishVote(live);
}
}
반응형