ݺߣ

ݺߣShare a Scribd company logo
예제로 배우는 이더리움 결제
Hyocheol Chae
목차
• 결제 시스템 구조
• 이더리움 주소 생성
• 입금 처리
• 송금 / 환불
대상
• 이더리움이 어떻게 돌아가는지 알고 싶은 분들
• 이더리움 입출금 개발을 시작하시려는 분들
• Go-ethereum 소스코드 공부하시는 분들
한계
• 본 발표자료에 사용된 코드는 데모용으로 만든 것이기
때문에 실제 개발에는 더 많은 주의가 필요 합니다
Case Study: alfacoins.com
Case Study: alfacoins.com
Payment Solutions
• https://smartex.io/ (BTC, ETH)
• https://www.coinpayments.net/ (65 coins+)
• https://alfacoins.com (BTC, ETH)
Why Ethereum is great for payments
• Simpler (No UTXO - easy to make wallet)
• Cheap transaction fee (<$0.01)
• Scalable & Off-chain payment (http://raiden.network)
• Smart contract
• Not good for privacy (UTXO is better)
Raiden Network
• Scalable: it scales linearly with the number of participants (1,000,000+
transfers per second possible)
• Fast: Transfers are confirmed and final within the fraction of a second
• Confidential: Single transfers don’t show up in the global shared
ledger
• Interoperable: Works with any token that follows Ethereum’s
standardized token API
• Low Fees: Transaction fees can be 7 orders of magnitude lower than
on the blockchain
• Micro-payments: Low transaction fees allow to efficiently transfer tiny
values
Raiden : Complementary to Ethereum
• Vitalik Buterin: “State channels are an
important technology that has the potential to
greatly improve the scalability and privacy of
many categories of blockchain applications; in
conjunction with sharding and other privacy-
preserving cryptographic technologies, they are
an important ingredient in helping decentralized
systems to achieve the properties that
mainstream individual and institutional users
expect and deserve.”
• https://github.com/raiden-network/raiden
개발스택
• 이더리움 노드
• 로컬에 설치하면 속도가 매우 빠르지만
• 설치/운영 수고가 없는 infura.io 사용
• 개발 언어 + 라이브러리
• Go + Geth (as a RPC library)
이더리움 결제 고려사항
• 기능
• 특정 사용자용 이더리움 주소 생성 하여 입금 여부 실시간 확인
기능
• 입금 취소를 하는 경우 돈을 돌려줘야 하는데, 1ETH를 받으면 수
수료를 제외하고 송금하는 기능
• 장애처리
• 결제 누락
• 이중 지불
이더리움 노드 접속하기
• Geth에서 제공하는 EthereumClient 클래스 사용하여
Infura 접속
입금 주소 생성하기
• Go-ethereum 에서 제공하는 함수 이용하면 개인키와 주소를 쉽게 생
성 가능
• 개인키 = resPriv
• 공개키 = address
입금 확인
• 입금 확인에는 2가지 방법이 있다
• Polling : 정기적으로 최근 블럭-트랜잭션 목록을 전수 조사하여 입금
여부 확인
• Subscribe : 새로운 블럭이 들어올 때 마다 검사하는 기능
• SubscribeNewHead : 그냥 새로운 블럭이 들어오면 콜백 호출
• SubscribeFilterLogs : 필터 조건 (시작/종료 블럭, 관심 주소) 에 맞
는 블럭이 들어오면 콜백 호출 - (infura.io 에서는 사용 불가)
• 결제 주소마다 스마트컨트랙 생성후 결제시 로그를 남기는 방식으로 구현 가능. 그러나
스마트컨트랙 생성에 Gas가 소요되므로 좋은 방법은 아닌것 같음
입금 확인 : Polling Example
입금확인 : 인덱싱 서버와 입금확인 분리 패턴
• 인덱싱 서버 : 이더리움 트랜잭션 목록을 매번 읽어서
DB에 기록하는 서버
• 입금확인 서버 : DB에서 원하는 조건이 만족하면 입금으
로 처리
입금 확인 : 트랜잭션 목록 서명 검증
• Go-Ethereum 에서 트랜잭션 목록을 읽기 위해서는, 무
결성을 위해 전자서명이 검증된 값만 해석되도록 만들어
보안사고 방지
• 서명 클래스는 HomesteadSigner, FrontierSigner,
EIP155Signer 중에 하나를 고를 수 있는데 가장 최신
버전인 EIP155Signer 를 선택하면 잘 작동
• EIP155 Signer 란? Replay Attack 막기 위해 이더리움
블럭체인 코드가 바뀌면서 포크 발생
• ChainID 는 메인넷은 1로 고정됨, 테스트넷(ropsten)
은 3
이더리움 송금
• 준비
이더리움 송금
• 송금
이더리움 송금시 주의사항
• GasLimit 과 GasPrice 가 충분치 않으면 송금이 안됨
• 트랜잭션시 Nonce 값이 틀리면 아무 메시지도 없이 무
효처리되는데, 이 값은 누적 트랜잭션 횟수를 입력해줘
야 함 (NonceAt 함수 사용 추천)
• 송금을 하면 트랜잭션 해시 값이 만들어지는데 이 값을
이용해서 결과를 추적 가능
이더리움 송금 결과 체크
• 트랜잭션이 잘 수행되었는지 어떻게 아는가?
• 이더리움에는 영수증(Receipt) 이라는 개념이 있다
이더리움 송금 결과 체크 (Before Geth 1.7)
• TransactionReceipt 함수를 이용해 트랜잭션이 성공적
인지 확인 가능. 다만, Gas가 부족한 경우와 아닌 경우를
알기 어려운데 이는 gasUsed 와 gasLimit 을 비교해서
판별 가능 (어디까지나 확률적)
이더리움 송금 결과 체크 (Metropolis)
• 최신 Geth 1.7 에서는 TransactionReceipt 함수를 호출
하면 트랜잭션이 성공했는지 알려준다.
•
이더리움 송금 결과 체크 (Metropolis)
Receipt 구조체
type Receipt struct {
// Consensus fields
PostState []byte //
Failed bool // 송금의 성공여부
CumulativeGasUsed *big.Int // EVM 실행에 사용된 가스 사용량
Bloom Bloom // 로그 인덱스을 빠르게 할 Bloom 필터
Logs []*Log // 로그 목록 (컨트랙에서 남길 수 있음)
// Implementation fields (don't reorder!)
TxHash common.Hash
ContractAddress common.Address
GasUsed *big.Int
}
Receipt 는 언제 만들어지나?
• 송금 (정확히는 ApplyTransaction) 이 발생할 때
receipt := types.NewReceipt(root, failed, usedGas) // 영수증 생성
receipt.TxHash = tx.Hash() // 트랜잭션 해쉬값을 영수증에 쓴다
receipt.GasUsed = new(big.Int).Set(gas) // 사용된 가스값 저장
// 트랜잭션이 Contract 생성하는 경우는 대상주소가 Nil
if msg.To() == nil {
receipt.ContractAddress = crypto.CreateAddress(vmenv.Context.Origin, tx.Nonce())
}
// 영수증에 로그 정보와 블룸필터 정보를 쓴다
receipt.Logs = statedb.GetLogs(tx.Hash())
receipt.Bloom = types.CreateBloom(types.Receipts{receipt})

More Related Content

예제로 배우는 이더리움 결제구현 (거래소 지갑 구현 예시)

  • 1. 예제로 배우는 이더리움 결제 Hyocheol Chae
  • 2. 목차 • 결제 시스템 구조 • 이더리움 주소 생성 • 입금 처리 • 송금 / 환불
  • 3. 대상 • 이더리움이 어떻게 돌아가는지 알고 싶은 분들 • 이더리움 입출금 개발을 시작하시려는 분들 • Go-ethereum 소스코드 공부하시는 분들
  • 4. 한계 • 본 발표자료에 사용된 코드는 데모용으로 만든 것이기 때문에 실제 개발에는 더 많은 주의가 필요 합니다
  • 7. Payment Solutions • https://smartex.io/ (BTC, ETH) • https://www.coinpayments.net/ (65 coins+) • https://alfacoins.com (BTC, ETH)
  • 8. Why Ethereum is great for payments • Simpler (No UTXO - easy to make wallet) • Cheap transaction fee (<$0.01) • Scalable & Off-chain payment (http://raiden.network) • Smart contract • Not good for privacy (UTXO is better)
  • 9. Raiden Network • Scalable: it scales linearly with the number of participants (1,000,000+ transfers per second possible) • Fast: Transfers are confirmed and final within the fraction of a second • Confidential: Single transfers don’t show up in the global shared ledger • Interoperable: Works with any token that follows Ethereum’s standardized token API • Low Fees: Transaction fees can be 7 orders of magnitude lower than on the blockchain • Micro-payments: Low transaction fees allow to efficiently transfer tiny values
  • 10. Raiden : Complementary to Ethereum • Vitalik Buterin: “State channels are an important technology that has the potential to greatly improve the scalability and privacy of many categories of blockchain applications; in conjunction with sharding and other privacy- preserving cryptographic technologies, they are an important ingredient in helping decentralized systems to achieve the properties that mainstream individual and institutional users expect and deserve.” • https://github.com/raiden-network/raiden
  • 11. 개발스택 • 이더리움 노드 • 로컬에 설치하면 속도가 매우 빠르지만 • 설치/운영 수고가 없는 infura.io 사용 • 개발 언어 + 라이브러리 • Go + Geth (as a RPC library)
  • 12. 이더리움 결제 고려사항 • 기능 • 특정 사용자용 이더리움 주소 생성 하여 입금 여부 실시간 확인 기능 • 입금 취소를 하는 경우 돈을 돌려줘야 하는데, 1ETH를 받으면 수 수료를 제외하고 송금하는 기능 • 장애처리 • 결제 누락 • 이중 지불
  • 13. 이더리움 노드 접속하기 • Geth에서 제공하는 EthereumClient 클래스 사용하여 Infura 접속
  • 14. 입금 주소 생성하기 • Go-ethereum 에서 제공하는 함수 이용하면 개인키와 주소를 쉽게 생 성 가능 • 개인키 = resPriv • 공개키 = address
  • 15. 입금 확인 • 입금 확인에는 2가지 방법이 있다 • Polling : 정기적으로 최근 블럭-트랜잭션 목록을 전수 조사하여 입금 여부 확인 • Subscribe : 새로운 블럭이 들어올 때 마다 검사하는 기능 • SubscribeNewHead : 그냥 새로운 블럭이 들어오면 콜백 호출 • SubscribeFilterLogs : 필터 조건 (시작/종료 블럭, 관심 주소) 에 맞 는 블럭이 들어오면 콜백 호출 - (infura.io 에서는 사용 불가) • 결제 주소마다 스마트컨트랙 생성후 결제시 로그를 남기는 방식으로 구현 가능. 그러나 스마트컨트랙 생성에 Gas가 소요되므로 좋은 방법은 아닌것 같음
  • 16. 입금 확인 : Polling Example
  • 17. 입금확인 : 인덱싱 서버와 입금확인 분리 패턴 • 인덱싱 서버 : 이더리움 트랜잭션 목록을 매번 읽어서 DB에 기록하는 서버 • 입금확인 서버 : DB에서 원하는 조건이 만족하면 입금으 로 처리
  • 18. 입금 확인 : 트랜잭션 목록 서명 검증 • Go-Ethereum 에서 트랜잭션 목록을 읽기 위해서는, 무 결성을 위해 전자서명이 검증된 값만 해석되도록 만들어 보안사고 방지 • 서명 클래스는 HomesteadSigner, FrontierSigner, EIP155Signer 중에 하나를 고를 수 있는데 가장 최신 버전인 EIP155Signer 를 선택하면 잘 작동 • EIP155 Signer 란? Replay Attack 막기 위해 이더리움 블럭체인 코드가 바뀌면서 포크 발생 • ChainID 는 메인넷은 1로 고정됨, 테스트넷(ropsten) 은 3
  • 21. 이더리움 송금시 주의사항 • GasLimit 과 GasPrice 가 충분치 않으면 송금이 안됨 • 트랜잭션시 Nonce 값이 틀리면 아무 메시지도 없이 무 효처리되는데, 이 값은 누적 트랜잭션 횟수를 입력해줘 야 함 (NonceAt 함수 사용 추천) • 송금을 하면 트랜잭션 해시 값이 만들어지는데 이 값을 이용해서 결과를 추적 가능
  • 22. 이더리움 송금 결과 체크 • 트랜잭션이 잘 수행되었는지 어떻게 아는가? • 이더리움에는 영수증(Receipt) 이라는 개념이 있다
  • 23. 이더리움 송금 결과 체크 (Before Geth 1.7) • TransactionReceipt 함수를 이용해 트랜잭션이 성공적 인지 확인 가능. 다만, Gas가 부족한 경우와 아닌 경우를 알기 어려운데 이는 gasUsed 와 gasLimit 을 비교해서 판별 가능 (어디까지나 확률적)
  • 24. 이더리움 송금 결과 체크 (Metropolis) • 최신 Geth 1.7 에서는 TransactionReceipt 함수를 호출 하면 트랜잭션이 성공했는지 알려준다. •
  • 25. 이더리움 송금 결과 체크 (Metropolis)
  • 26. Receipt 구조체 type Receipt struct { // Consensus fields PostState []byte // Failed bool // 송금의 성공여부 CumulativeGasUsed *big.Int // EVM 실행에 사용된 가스 사용량 Bloom Bloom // 로그 인덱스을 빠르게 할 Bloom 필터 Logs []*Log // 로그 목록 (컨트랙에서 남길 수 있음) // Implementation fields (don't reorder!) TxHash common.Hash ContractAddress common.Address GasUsed *big.Int }
  • 27. Receipt 는 언제 만들어지나? • 송금 (정확히는 ApplyTransaction) 이 발생할 때 receipt := types.NewReceipt(root, failed, usedGas) // 영수증 생성 receipt.TxHash = tx.Hash() // 트랜잭션 해쉬값을 영수증에 쓴다 receipt.GasUsed = new(big.Int).Set(gas) // 사용된 가스값 저장 // 트랜잭션이 Contract 생성하는 경우는 대상주소가 Nil if msg.To() == nil { receipt.ContractAddress = crypto.CreateAddress(vmenv.Context.Origin, tx.Nonce()) } // 영수증에 로그 정보와 블룸필터 정보를 쓴다 receipt.Logs = statedb.GetLogs(tx.Hash()) receipt.Bloom = types.CreateBloom(types.Receipts{receipt})