어제에 이어 복습부분과 새롭게 부분 배운 그리고 Solidity를 배운 부분에 대해서 정리해보도록 하겠다.
우리가 들어갔을때 항상 풀노드처럼 행동 할 필요는 없고, SPV노드처럼 행동을 한다.
SPV노드는 풀노드처럼 전체 정보를 다 가지고 있지 않기 때문에 SPV노드가 풀노드에게 요청을 해야하는데 어떻게 해야하는지와 내가 새로운 풀노드가 되고싶어서 네트워크에 참가했을때 어떤형식으로 주변 이웃노드들의 정보를 얻고, 어떤 형식으로 체인을 동기화 시키는지에 대해 공부할 예정.
수업에서는 큰 맥락을 이해하고 세부내용에 대해서 이해를 해야한다. 세부적인 부분만 신경쓰다보면 모든 내용이 다 연결되어 설명이 되는데 내가 기억하는 내용 자체가 다 조각난 기억으로 남겨질 수 있다. 그러다보면 두가지 다 놓치게 된다.
'머클루트(Merkle Root)'란 블록체인의 원소 역할을 수행하는 블록의 부분에 저장된 트랜잭션들의 해시트리라고 생각하면 된다.
'머클트리(Merkle Tree)' 혹은 '해시트리(Hash Tree)'라는 데이터 구조는 Ralph Merkle이라는 사람이 1979년에 특허를 낸 개념이다. 머클트리의 목적은 빠른 검색이 아니라 데이터의 간편하고 확실한 인증을 위해 사용한다.
지갑 어플이 깔려있는 테블릿이나 휴대폰도 노드로 생각할 수 있다.
내가 유지하지 않으면 정보를 받을 수 없다. 그리고 내가 일으킨 거래를 전파를 시킬 수 없다.
그래서 기본적으로 이웃간의 연결 유지 기능이 있다.
모든 노드가 동등한 위치에 있지만 하는 역할이 다 다르다.
풀노드와 대비되는 것이 SPV Node.
두 노드는 가지고 있는 정보의 양이 다르다. 그렇기 때문에 거래를 검증하거나 할때 검증을 하는 방법이 다르다.
역할에 따라 지위가 정해지는것은 아니지만 확실히 풀노드가 유리한 부분은 있다.
이 과정들은 실제로 어떤 정보를 주고 받기전에 내가 가지고 있는 정보나 나 자신에 대한 정보를 상대방에게 넘겨주는 것이다.
A가 version이라는 메세지를 보내고 B가 니가 version이라고 보낸 메세지를 받았어 라는 verack 답장을 보낸다.
그리고 B가 version을 보낸다.
그리고 A는 보내준 version을 받았다고 verack를 보낸다.
안정적으로 작동하는 노드들의 리스트.
A가 자신의 addr을 보낸다.
A가 addr을 보내고 나면 B에게 이웃노드들에 대한 정보를 달라고 geraddr을 보낸다.
B가 getaddr을 받으면 자신이 가지고 있는 이웃노드들에 대한 정보를 보낸다.
A와 B가 getblocks를 통해 가장 마지막 블록을 확인한다.
더 긴체인을 보유한 B가 A에게 inv라는 메세지를 보낸다.(그 안에는 공유받아야 할 첫 500개 노드의 해시정보가 있다.)
만약 A가 일정 해시정보를 가지고 있어 500개가 다 필요하지 않다면 자신이 가진것 외에 필요한 양만큼의 블록만 달라고 getdata 요청을 보낸다.
B는 요청받은 블록을 A에게 보내준다. 한번 더 원하면 이 과정을 반복한다.
이 모든 과정이 최초로 네트워크에 들어와 처음 통신을 연결하고 동기화가 되는 절차에 대한 것.
앞의 전반적 내용은 새로들어간 풀노드가 어떻게 행동하는지에 대한 내용.
거래에 대한 정보가 없기 때문에 풀노드의 도움을 받아야함.
SPV노드는 정보가 없기 때문에 다른 경로로 거래를 검증함. 이를 위해 풀노드에게 정보를 요청하고 path를 받게됨.
path를 구하라는 문제가 나오면 지정된 해시와 반대에 위치하는 해시를 찾아주면 됨.
예시를 아래에 이미지로 붙이도록 하겠음.
새노드는 풀노드가 될지 SPV노드가 될지 선택할 수 있음.
새노드 - 풀노드 - 동기화과정(체인을 받아야하기 때문에)
그러면 두가지 문제에 직면하게 된다. 누구에게 연락할건지, 어떻게 연락할건지
누구에게 연락할건지는 시드노드들에게.
어떻게 연락할건지는 1) 연락의 시작(version을 주고받는걸로) 2) getblock(가장 마지막블록헤더 해시를 비교, inv 보내주고, getdata를 요청하면 block을 받음.)
이렇게 풀노드가 되기위한 동기화 과정을 거치게됨.
새노드 - SPV노드 - 검증을 받기위해서는 도움이 필요함.
도움을 풀노드에게 요청함.
풀노드에게 tx에 대한 정보를 요청
그에 대한 답변으로 path를 받음.
path는 이진트리와 관련이 있음.
그래서 이 과정을 거치고 나면 머클트리가 나옴.
// SPDX-License-Identifier: GPL-3.0
// 없으면 경고 먹음 / 라이센스
pragma solidity ^0.8.18;
//컴파일 버전 : 컴파일과 맞지 않거나 낮으면 안됨 실행안됨 / 왠만하면 18,18 고고
contract StoreandReturn {
uint a; //숫자형 변수 a
uint b; //숫자형 변수 b
uint c=2; // 숫자형 변수 c, 값은 2
// 상태 변수
// 수정하려면 돈든다
// view에 지역변수 선언하고 담아서 수정가능 -> view는 돈 안듬
// 돈들면 주황색이랑 콘솔에 녹색 스티커
// 함수이고, 이름은 getA, input값은 없음, public 하고 view 함, output 값은 1개 있음, uint 형임
function getA() public view returns(uint) {
return a;
}
function setA(uint _a) public {
a = _a;
}
function setAasFive() public {
a = 5;
}
function getB() public view returns(uint) {
return b;
}
function setB(uint _b) public {
b = _b;
}
function setBasSeven() public {
b = 7;
}
// 함수, 이름은 getAB, input 없음, public하고 view 함, output 값은 2개, 둘 다 uint형
function getAB() public view returns(uint, uint) {
return (a, b);
}
// view : 상태변수 참고가능 값 변경 불가능 -> 가스 안씀
// pure : 상태변수 변경 및 참조도 불가 -> 가스 안씀
// view, pure 없으면 가스비 나옴
//view와 pure 함수는 state variable(상태변수)의 값을 변화시키지는 않음 -> gas비 안씀
function getABC() public view returns(uint, uint, uint) {
return (a,b,c);
}
//숫자 _aa와 _bb를 받아서 이 2개의 숫자를 더한 결과값을 반환하는 함수 Add를 구현하세요.
function Add(uint _aa, uint _bb) public pure/*상태변수는 하나도 필요없을때 pure*/ returns(uint) {
return _aa + _bb;
}
// 숫자 a와 b를 갖고와서 이 2개의 숫자를 더한 결과값을 반환하는 함수 Add2를 구현하세요
function Add2() public view/*상태변수를 갖고오기 때문에 view로*/ returns(uint) {
return a+b;
}
}
상태변수는 contract와 function 사이 지정된 값을 지칭.
지역변수는 function안에 넣는 변수로 수정이 가능.
view : 상태변수 참고가능 값 변경 불가능 -> 가스 안씀
- 상태변수를 가져올때 view 사용.
pure : 상태변수 변경 및 참조도 불가 -> 가스 안씀
- 상태변수 하나도 없을때 pure 사용.
view, pure 없으면 가스비 나옴
view와 pure 함수는 state variable(상태변수)의 값을 변화시키지는 않음 -> gas비 안씀
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.18;
/*
계산기를 만드세요.
2개의 input 값을 받아 더한 값을 반환하는 함수 Add, 곱한 값을 반환하는 함수 Mul, 뺀 값을 반환하는 Sub, 몫을 반환하는 Div를 구현하세요
*/
contract Basic2 {
function Add(uint _a, uint _b) public pure returns(uint){
return _a+_b;
}
function Mul(uint _a, uint _b) public pure returns(uint) {
return _a*_b;
}
function Sub(uint _a, uint _b) public pure returns(uint) {
return _a-_b;
}
function Div(uint _a, uint _b) public pure returns(uint, uint) {
return (_a/_b, _a%_b);
}
}
민서강사님이 문제를 내셨는데 못풀었음..ㅜㅜ
- input값에 들어가는 _a , 즉 a앞에 언더바는 큰 의미가 없음. a와 구분을 두기 위해서 작성된 것이라고 매니저님이 말씀하심. a로 적어도 상관없는데 상태변수가 있거나 a값이 이미 있는경우에는 작성해주는게 좋음.
나누기의 경우 _a/_b 로 표현할 수 있는데 그러면 "몫"만 나오게 됨. 나머지까지 나오게 하려면 결과값이 2개가 되기 때문에 output을 두개 적어주고 아래에 _a%_b를 작성해줌.
오늘 수업 마지막에 민서강사님께 질문을 했는데 뭔가 나만 모르는 것 같고 하필 수업 끝날 시간이라 사람들이 내가 질문하면 싫어할 것 같고, 관심도 쏠리는 것 같아서 부끄럽고 숨고 싶었는데 모르는부분 질문은 또 하고싶고.. 참 힘들었다..
그래도 착한 동료들이 위로도 해주고 도와줘서 금방 기분을 회복할 수 있었다.😊
내일은 좀 더 단단한 마음으로 하루를 시작할 수 있을 것 같다. 오늘도 복습 끝!