추가 공부 [Solidity - 4, betch Transaction]

Lumi·2022년 2월 3일
0

Block_Chain_Project

목록 보기
29/30
post-thumbnail

🔥 Solidity - 4

아마 마지막으로 작성하는 부분이 될꺼 같고 이제는 Golang을 공부할것 같습니다.

이번 글은 코드적인 부분보다는 좀 이런 부분을 추가하려고 하고 있다?? 이런 내용이 될것 같고 내용은 Youtube를 참고하였습니다.

Uniswap에서도 활용하고 있으며 아직은 불완전한 형태입니다.

betch Transaction에 관한 내용으로 betch란 모아서 처리하는?? 의미가 있기 떄문에 트랜잭션을 모아서 처리한다는 내용의 글이 되겠습니다!

🔨 betch Transaction

ERC-20기준으로 트랜잭션을 하나 소출하는데에 최소 소요되는 가스비는 21000입니다.

현 시점에서 작은 데이터만을 처리하는 가스비가 굉장히 많이 발생을 하고 있는 시점이고

이러면 이러한 작은 데이터마다 21000의 가스비가 소비되는 형태 입니다.

이렇게 발생하는 최소단위의 가스비를 줄일수 있는 방법에는 무엇이 있을까요??

바로 한번에 모아서 처리를 하는 것 입니다.

  • 저 같은 경우에는 Youtube를 접하여 알게 되었지만 실제 EIP라던가 논문 자료로도 해당 방법이 연구되고 있다고 합니다.
20개의 트랜잭션을 사용자들이 개별적으로 전송을 하면 20 * 21000이라는 최소 가스비가 소요되게 됩니다.

하지만 만약 이를 모아서 한번에 처리를 하게 된다면 21000이라는 최소 가스비만이 소요 됩니다.

이러한 부분을 이더리움 재단에서는 따로 지원을 하지 않고 있기 때문에 많은 사람들은 미들웨어 즉 제 3자를 중간에 포함시켜서 해결을 하고자 하였습니다.

하지만 이런 부분에 있어서 보안, 중앙화등 많은 문제점이 야기될수 있기 떄문에 고려되지 않았고 Uniswap에서는 permit이라는 방법을 통해서 해결하고 있습니다.

Uniswap에서의 permit함수

function permit(addresss owner, address spender, uint value, uint deadline, uint8 v. bytes32 r, btyes32 s) external {
	require(deadline >=block.timestamp);
	btyes32 digest = keccak256(
		abi.encodePacked(
			keccak256(abi.encode(상수, owner, spender, value, nonces[owner]++, deadline))
		)
	)

	addresss recover_address = ecrecover(digest,v,r,s);
	require(recover_address != address(0) && recover_address == owner);
	_approve(owner, spender, value);
}
  • 보고 작성한 부분이라서 실제로는 조금 다릅니다.
  • 이곳에서 사용한는 nonce는 mapping값으로 트랜잭션 전송수를 추적하기 위해서 사용됩니다.
  • 내용이 많이 어려워서 살짝 참고했던 youtube의 말을 인용하겠습니다.
이더리움은 타원곡선 알고리즈에 의해서 서명값을 통해 주소값을 뺴올수 있습니다

그러기 떄문에 v,r,s라는 서명값을 가지고 있으면 주소를 찾을수 있고
- 여기에서 v,r,s는 저희가 web3를 사용해서 signTransaction할떄 나오는 트랜잭션 데이터를 말합니다.

Solidity내부 함수인 ecrecover을 통해서 서명을 한 주체를 뽑아낼 수 있습니다.

그러기 때문에 올바르게 만들어진 서명이라는 전제가 깔려 있다면 사용자를 파악할수 있고 이런 과정을 통해 검증을 한뒤에 `_approve`를 호출합니다.

이런 과정의 함수가 추가된다면 저희는 approve -> transferFrom이라는 이전의 과정이 permit함수를 활용하는 하나의 함수를 통해서 간단하게 작동 가능합니다.

function transferFromWithPermit(address to, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external returns(bool){
	permit(msg.sender, address(this), value, deadline, v, r, s);
	return transferFrom(msg.sender, to, value);
}
  • 이런 함수를 따로 활용을 한다면 한번에 실행이 가능하며 최소 가스비를 줄일수가 있습니다.

하지만 제가 실제로 Remix에서 테스트 해본 결과 이전의 방식에 비해 별다른 차이점이 없음과 동시에 오히려 이전의 방식이 더 적은 가스비를 소비하였습니다.

  • 이전의 방식 : 103,678gas
  • 바꾼 방식 : 107,297gas

왜냐하면 바꾸어서 사용하는 방식은 더 많은 상태를 변경시키기 떄문입니다.

  • 대표적으로는 nonce가 있습니다.

또한 이러한 방법에도 다른 많은 문제점이 많습니다.

기본적으로 Dapp들은 타이밍에 굉장히 민감한 시스템 입니다.

  • 거래, 경매, 플래시론 등등

하지만 이런 방식은 트랜잭션을 모아서 처리하는것과 같기 떄문에 트랜잭션을 종합하는데에 걸리는 시간으로 인해서 시간차이가 발생을 하게 됩니다.

시간적인 차이가 발생하는 것은 굉장히 바람직하지 않은 상태이며 이런 문제점을 EIP에서는 많은 가스비를 제시함으로써 빠르게 트랜잭션을 처리하여 시간차이를 줄이자고 제시를 하고 있습니다.

  • 말이 그럴싸 한게 구현이 성공적으로 완료가 되면 gas비가 어차피 줄어들게 되고 줄어든 가스비에서 더 많은 가스비를 사용해도 이전보다는 적은 gas비가 사용이 됨과 동시에 더 빠르게 처리가 될수 있기 때문입니다.

추가적인 문제점은 context문제점 입니다.

현재 ETH컨트랙트 들은 msg.sender을 많이 사용하고 있지만 만약 사용자가 트랜잭션을 전송을 하는 것이 아니라 모아서 한번에 전송을 하게 되면 전송자의 msg.sender가 유지되지 않을것 입니다.

  • 기존에는 사용자가 실행을 하기 떄문에 msg.sender가 사용자가 되었지만 바뀌게 된다면 모아서 처리하는 컨트랙트가 msg.sender가 되게 된다.

이러한 문제점을 해결하기 위해서는 단순히 새로 배포하는 방법밖에 없습니다...ㅠㅠ

따라서 더 안정적이고 효율적인 방법이 필요했고 이런 문제점을 해결하기 위해서 오프체인 상태를 사용하는 것으로 방향을 바꾸게 되었습니다.

  • 이부분은 논문 내용이라고 합니다.

offchain방법

오프체인을 활용하는 방법은 MultiCall과 유사합니다.

오프체인에서 트랜잭션들을 모아서 온체인에 트랜잭션을 쏘아주는 방식으로 작동을 합니다.

  • 물론 이러한 방식은 오프체인에서 조작 가능성이 있기 떄문에 온체인에서 많은 검증이 들어가야 합니다.
  • 정리하면서 이 부분에 대해서도 검증이 많을수록 더 많은 가스비가 소요될꺼 같다는 생각이 드네요 ㅠㅠ

온체인에서는 리플레이 어택을 방지하기 위한 방법으로는 nonce방법이 있지만 비 효율적 이기 떄문에 오프체인에서 리플레이 어택을 방지하는 방법이 필요합니다.

  • 리플레이 어택이란 이전에 트랜잭션을 다시 전송하는 것을 말합니다.

그래서 연구 하는 부분은 트랜잭션을 전송하고자 하는 호출자가 트랜잭션이 안전하다는 검증이 끝날떄까지 기다리는 방식으로 연구를 하고 있다고 합니다.

  • 단순히 트랜잭션을 전송하고 끝!! 이 아닌 방식으로 가정을 하였다고 합니다.

아이디어는 굉장히 간단합니다.

오프체인에서 모아놓은 트랜잭션을 다시 사용자들에게 한번더 확인을 한뒤에 트랜잭션을 실제로 발생시키는 것 입니다.

  • 이런 방식이면 위변조, 리플레이 어택등 모든 공격에 대응 가능합니다.

  • 이 내용을 보자마자 PBFT나 jWT, 비대칭키 등등이 생각이 나네요 ㅎㅎ

🔥 후기 및 느낀점

음 처음에는 Solidity의 코드적인 부분을 분석해보고 좀더 멋있고 안정적인 코드를 작성해보고 싶어서 공부를 시작하였습니다.

물론 처음에는 이러한 부분에 대하여 살짝이라도 다루었습니다.

  • unchecked, scope등등

하지만 이게 가다보니 뭔가 이론적인 내용?? 이런 부분이 주를 이루게 되었던것 같습니다.

  • 불만은 없습니다. 흥미롭고 재미있었습니다.

제가 작성한 모든 부분에 대해서 완벽하게 숙지했다라고 말할수는 없습니다.

워낙 짧은기간안에 많은 것을 배웠다고 생각을 하고 많은 부분에서 부족하다고 생각을 하고 있습니다.

틈틈히 다시 읽어보면서 기록하기 위해 적은 글이기 떄문에 반복적으로 읽어볼 것이고

후에 활용해야 할 상황이 온다면 제가 쓴 글을 참고하여 코드를 작성해볼 것입니다.

이제 Solidity공부는 이쯤할꺼 같습니다.

오만하지만 개인적으로는 작성한 부분에 대해서만 조금 익숙해진다면 왠만한 코드는 다 작성가능하다?? 라는 생각이 드네요;; 오만한놈 ㅠ

이제는 Golang을 공부해보고자 합니다.

사실 Golang이라는 언어가 Dapp를 구현하는데에는 사용되지 않고 메인넷을 개발하는 부분에서 많이 사용이 되지만

블록체인에서 Golang은 많은 범용성이 있다고 생각을 하기 떄문에 이전에 못했던 Golang을 다시 공부하려고 합니다.

  • 책도 이미 구입을 해놔서 열심히 해볼겁니다!!

아직도 많이 부족합니다. 그래서 많이 배울수 있다는 부분에 중점을 두고 있습니다.

감사합니다!

추가사항 - Klaytn마이그레이션

Golang을 공부하고 싶었지만 프로젝트를 Klaytn으로 마이그레이션 해야 한다는 변경사항이 생겨서 이부분을 처리한뒤에 Golang공부하고자 합니다.

일단 web3코드를 전부 Klaytn으로 수정을 해야 합니다.

Klaytn의 경우에는 TPS가 빠르기 떄문에 따로 서버를 통해 처리해줄 필요가 없다고 생각을 합니다.

  • 즉 betch서버를 제외할것 입니다.

대략적으로 생각해둔 부분은 이와 같습니다.

1. NFT발행, token 등등 모든 과정을 온체인으로 구현

2. 경매 기능 같은 경우에는 모든 경매에 bidding하지만 bidding하는 부분은 feeFayer를 통해 가스비를 어드민 계정에서 지불

3. block.timeStamp를 활용해볼 예정

대략적인 구성은 이와 같습니다.

profile
[기술 블로그가 아닌 하루하루 기록용 블로그]

0개의 댓글