티스토리 뷰
아래 실습을 시작하기에 앞서 개인지갑에 비트코인을 넣는 것 먼저 하셔야 할텐데요. 개인지갑에 비트코인을 충전하는 방법은 이 영상을 참고해 주세요.
개인지갑에 비트코인이 충전되셨다면, 이제부터 시작해 봅시다!
cryptos 설치
pip install cryptos requests
※ 아래 코드에서 requests 모듈을 직접 사용하는 것은 아니지만, cryptos 내부적으로 requests를 사용하므로 사전 설치가 필요합니다.
비트코인 지갑 생성
>>> from cryptos import *
>>> priv = sha256('your brain wallet password')
>>> priv
'48595ca03139282ad422a486ffb0e5828a22e1426992f48b9bce12951f952142'
>>> pub = privtopub(priv)
>>> pub
'04dc2e4727338487a6d5d64cf455e98ceac8e0a97ad42ba5abfac9f73b5ce65484fe5d45dd55527a4de849082a0c485eeb72798be80a2ea9822050cec5e9cb9c66'
>>> addr = pubtoaddr(pub)
>>> addr
'1Mfy6uiX3cZc15RmPkLR5hpGR32taCjY4g'
개인지갑에서 출금하기
* 아래 예시는 실제 비트코인 메인넷에서 비트코인을 옮기는 코드입니다. 대량의 비트코인을 옮기실 때는 특별히 주의하시고요. 소량으로 충분히 연습이 되신 분만 큰 금액에 대해서 시도해 보시기 바랍니다.
from cryptos import *
c = Bitcoin()
from_address = 'address1'
inputs = c.unspent(from_address)
balance = sum([i['value'] for i in inputs])
fee = 1500
to = 'address2'
outs = [{'value': balance - fee, 'address': to}]
tx = c.mktx(inputs, outs)
signed_tx = c.signall(tx, priv)
# send tx to bitcoin node
c.pushtx(signed_tx)
- outs 의 value 는 사토시 단위(1 satosh == 0.00000001)
- `unspent()` 와 `pushtx()` 수행은 반드시 인터넷 연결 필요
- unspent() 의 경우 승인되지 않은 utxo 도 함께 리턴이 됨
- 하지만 승인되지 않은 utxo 를 사용하려고 하면 아마도 오류가 발생하지 않겠나 싶음
- `출력 - 입력` 은 수수료가 됩니다
- 수수료는 적당히 알맞은 값으로 확인하여 계산해 주어야 함
- 수수료를 지나치게 저렴하게 설정할 경우에는 c.pushtx() 수행시 풀노드가 해당 트랜잭션을 받아주지 않고 400오류 뱉음
- 22/9/6 테스트 결과
- 수수료 240Sat 로 테스트시 400 오류 확인
- 수수료 250Sat 로 테스트시 성공!
- 10분 안에 거래 체결됨 확인
- 하지만 이렇게 낮은 수수료로는 트랜잭션 자체가 풀노드에서 거절되는 경우가 더 많음
- 멤풀 상황이 좋으면 accept 되어지기도 함
- 수수료는 최대한 거절 안되는 선에서 눈치게임을 해야함
- 일단 풀노드에게 거래가 받아들여지기만 한다면 해당 거래는 곧(10~20분 내에) 승인이 될 것으로 기대해 좋음
- 수수료 계산 시 참고
- 트랜잭션 올리기 전 유효성 검증
- https://live.blockcypher.com/btc/decodetx/
- 여기서 priv 가 유효한지 여부는 확인하지 않음
실전 예시
>>> c = Bitcoin()
>>>
>>> inputs = c.unspent('1A6LBamAnquzSZdiETrE7XJcakTNFrffEC')
>>> inputs
[{'output': '103d2fb7f4b9bbe62530ea464627237fa6a2983cc42f4d2b4b94ab0b23b13535:0', 'value': 28600}]
>>> balance = sum(list(map(lambda o: o['value'], inputs)))
>>> fee = 1500
>>> outs = [{'value': balance - fee, 'address': '1LLQccvbR37ixxwx7uC5NQyAAf871ATKHG'}]
>>> tx = c.mktx(inputs, outs)
>>> tx
{'locktime': 0, 'version': 1, 'ins': [{'script': '', 'sequence': 4294967295, 'outpoint': {'hash': '2dc4276f4b88134b7253286ea9bcbfb9451fdc7bc6ac8f51835e23bd5eee3814', 'index': 1}, 'amount': 30000}], 'outs': [{'script': '76a914d4160157d591f11dd2b5f6322b3f5c5dc041e0fb88ac', 'value': 28600}]}
>>>
>>> priv = 'your priv'
>>> signed = c.signall(tx, priv)
>>> signed
'01000000011438ee5ebd235e83518facc67bdc1f45b9bfbca96e2853724b13884b6f27c42d010000008a47304402203401acc754df15545ad9afa1f640eb7b01a6f0c7ad8cac7a3d5f058f19aef14602207e942e4641821d42deea1b2b4e460b8990d01c073f4f31c1bad27bdac9f10146014104e8d75e253e1c223ede954d6c503f0c321070a8adcaab728163c0806b354a5eeb961318e7bf6e2425493345b55433184bcc6adef57c384577227070c3bf5028f3ffffffff01b86f0000000000001976a914d4160157d591f11dd2b5f6322b3f5c5dc041e0fb88ac00000000'
>>> c.pushtx(signed)
{'status': 'success', 'data': {'txid': '103d2fb7f4b9bbe62530ea464627237fa6a2983cc42f4d2b4b94ab0b23b13535', 'network': 'BTC'}}
>>>
온체인 거래 기록 https://www.blockchain.com/btc/tx/103d2fb7f4b9bbe62530ea464627237fa6a2983cc42f4d2b4b94ab0b23b13535
priv 디지털서명이 유효하지 않으면, pushtx() 에서 아래와 같이 오류 발생. 수수료가 지나치게 적은 경우에도 동일 오류 발생함. 구체적으로 오류 발생 원인이 무엇인지는 알랴주지 않음;
>>> c.pushtx(invalid_signed)
<Response [400]>
>>>
Decode Hex 예시
위에서 서명된 트랜잭션 값은 아래와 같이 디코드하고 유효여부를 확인할 수 있습니다.
https://live.blockcypher.com/btc/decodetx/
Reference
https://github.com/primal100/pybitcointools#example-usage---the-long-way-best-way-to-learn--
블로그내 관련 글
https://www.youtube.com/watch?v=1yHNTFx9SVw
'비트코인 공부' 카테고리의 다른 글
인터넷 연결없이 안전하게 개인지갑의 비트코인을 출금하는 방법 (3) | 2022.09.01 |
---|---|
2^256 얼마나 큰 수 일까 (1) | 2022.08.31 |
비트코인 해킹 가능할까 (2) | 2022.08.30 |
니모닉월렛과 브레인월렛 비교 (0) | 2022.08.29 |
파이썬으로 비트코인 개인지갑 만드는 방법 (32) | 2022.08.28 |