๋นํธ์ฝ์ธ์ ํธ๋์ญ์ ์ ๋ํด ์์๋ณด์.
Transaction
- ์์์ ๋คํธ์ํฌ ํน์ ๋๋ฐ์ด์ค์ ์ด๋ํ๊ธฐ ์ํ ๊ณต๊ฐํค์ ๋น๋ฐํค์ ์ง๋ ฌํ ๋ฐฉ๋ฒ์ ๋ํด ์์๋ณด์๋ค.
- ๋ฌผ๋ก ๊ทธ์ ๋ํ ํ์ฑ๊น์ง ๊ฐ์ด ๋ฐฐ์ ๋ค.
- ํ์ฌ๊น์ง ํน์ ๊ฐ์ธ์ด ์ผ๋ง์ ๋นํธ์ฝ์ธ์ ๋ณด๋๋ค๋ ์ฌ์ค(๋ฌธ์)์ ์ฆ๋ช ํ ์ ์๊ณ (์๋ช /๊ฒ์ฆ ์๊ณ ๋ฆฌ์ฆ)
- ์ด๋ฅผ ๋คํธ์ํฌ์ ํ์, ๋ถํน์ ๋ค๋ฅธ ๋ ธ๋๋ค์ด ์ด ์ ๋ณด๋ฅผ ๋ฐ์ ํด๋ (Decode)ํ ์ ์์์ ๋ฐฐ์ ๋ค.
- ๊ทธ๋ฐ๋ฐ, โ์ผ๋ง์ ๋นํธ์ฝ์ธ์ ๋ณด๋๋คโ๋ผ๋ ์ฌ์ค์ ๋ํด์๋ ์ด๋ป๊ฒ ๊ตฌ์ฑ๋์๋์ง ๋ชจ๋ฅธ๋ค.
- ์ฐ๋ฆฌ๋ ์ด๋ฌํ ํํ์ ํ์๋ฅผ ์์ โ๊ฑฐ๋โ๋ผ๋ ๋จ์ด๋ก ์ธ์ํ๊ณ ์๋ค.
- ๊ทธ๋ ๋ค๋ฉด ๋นํธ์ฝ์ธ์์์ ๊ฑฐ๋๋ ์ด๋ค์์ผ๋ก ๊ตฌ์ฑ๋์ด ์์๊น?
- A, B ๋๋ช
์ ์ฌ๋์ ๊ณ์ข์ ์ ํ๋ ๊ฒ์ฒ๋ผ ๋์ด ์์๊น?
- A: ๋ณด๋ธ์ด(A), ๋ฐ๋์ด(B) ๊ธ์ก(30000)
- ๊ทธ ๊ฑฐ๋๋ฅผ ์ฒ๋ฆฌํ๋๋ฐ ์์ด ๊ธฐ์ ์ ์ธ ์ ์ฝ์ ์๋๊ฐ? ๊ทธ๊ฑธ ์ด๋ป๊ฒ ํด๊ฒฐํ ๊น?
- ์ด์ ๋ํด์ ์์๋ณด๊ฒ ๋ค.
Transaction Components
- Version
- Inputs
- Outputs
- Locktime
010000000181379011acb80925dfe69b3def355fe914bd1d96a3f5f71bf8303c6a989c7d10000000
06b483045022100ed81ff192e75a3fd2304004dcadb746fa5e24c5031ccfcf2132060277457c98f02
207a986d955c6e0cb35d446a89d3f56100f4d7f67801c31967743a9c8e10615bed01210349fc4e631
e3624a545de3f89f5d8684c7b8138bd94bdd531d2e213bf016b278afeffffff02a135ef0100000000
1976a914bc3b654dca7e56b04dca18f2566cdaf02e8d9ada88ac99c39800000000001976a9141c4bc
762dd5423e332166702cb75f40df79fea1288ac19430600
Version: 01000000 (4bytes)
Inputs: 0181379011acb80925dfe69b3def355fe914bd1d96a3f5f71bf8303c6a989c7d10000000
06b483045022100ed81ff192e75a3fd2304004dcadb746fa5e24c5031ccfcf2132060277457c98f02
207a986d955c6e0cb35d446a89d3f56100f4d7f67801c31967743a9c8e10615bed01210349fc4e631
e3624a545de3f89f5d8684c7b8138bd94bdd531d2e213bf016b278afeffffff
- Input counts(Varint): 01
- Previous Tx ID(hash256): 81379011acb80925dfe69b3def355fe914bd1d96a3f5f71bf8303c6a989c7d1
- Previous Tx index: 0000000
0
- ScriptSig(Varint): 3045022100ed81ff192e75a3fd2304004dcadb746fa5e24c5031ccfcf2132060277457c98f02
207a986d955c6e0cb35d446a89d3f56100f4d7f67801c31967743a9c8e10615bed01210349fc4e631
e3624a545de3f89f5d8684c7b8138bd94bdd531d2e213bf016b278a
- Sequence: feffffff
Outputs: 02a135ef0100000000
1976a914bc3b654dca7e56b04dca18f2566cdaf02e8d9ada88ac99c39800000000001976a9141c4bc
762dd5423e332166702cb75f40df79fea1288
- Output counts(Varint): 02
- First
- Bitcoin amounts: a135ef0100000000
- ScriptPubKey: 1976a914bc3b654dca7e56b04dca18f2566cdaf02e8d9ada88ac
- Second
- Bitcoin amounts: 99c3980000000000
- ScriptPubKey: 1976a9141c4bc762dd5423e332166702cb75f40df79fea1288
Locktime: ac19430600
Version
- ๋ฒ์ ์ ํธ๋์ญ์ ์ ๋ฒ์ ์ ์๋ฏธํ๋ค.
- ๋นํธ์ฝ์ธ์ด ์๋ํ๋ ๋ฐฉ์์ ๊ธฐ๋ณธ์ ์ผ๋ก ๋คํธ์ํฌ์ด๋ค.
- ๋คํธ์ํฌ์ ์ฐธ์ฌํ๋ ๋ ธ๋๋ค์, ๊ฐ์ ์ฝ์ด ํ๋ก๊ทธ๋จ์ ์ค์นํ๊ณ ์ ํด์ง ๊ท์ฝ์ ๋ฐ๋ผ ๋ค์ด์ค๋ ๊ฑฐ๋๋ฅผ ์ฒ๋ฆฌํ๋ค.
- ์ด๋ ๊ณง ์ฝ์ด ํ๋ก๊ทธ๋จ์ด ์ ๋ฐ์ดํธ๋๋ค๊ณ ํด์ ๋ชจ๋ ๋ ธ๋๋ค์ด ์ต์ ํ๋ก๊ทธ๋จ์ ์ฌ์ฉํ๋ ๊ฒ์ด ์๋์ ๋งํ๋ค.
- ๋ง์ฝ ๊ฑฐ๋(Transaction)์ ๊ตฌ์ฑํ๋ ๋ฐฉ๋ฒ์ด ๋ณ๊ฒฝ๋์์ ๊ฒฝ์ฐ, ๊ทธ ์ ๋ณด๋ฅผ ์๋ ค์ฃผ์ง ์๋๋ค๋ฉด ๋ ธ๋๋ค์ ์ด๋ฅผ ์ด๋ป๊ฒ ์ฒ๋ฆฌํ ์ง ์ ์ ์๋ค.
- ๊ทธ๋ ๊ธฐ์ ํธ๋์ญ์ ์ ์ถ๊ฐ๋๋ ๋ถ๊ฐ๊ธฐ๋ฅ์ ๊ด๋ฆฌํ๊ธฐ ์ํด ๋ฒ์ ์ ์ถ๊ฐํ๋ค.
Inputs
- ์ฌ๋ฌ๊ฐ์ ์ ๋ ฅ์ ๊ฐ์ง ์ ์๋ค.
- ์ด์ ํธ๋์ญ์ ์ ์ถ๋ ฅ์ ์ฐธ์กฐํ์ฌ ํด๋น ๋นํธ์ฝ์ธ์ ์์ ๊ถ์ ํ์ธํ๋ค.
- ์์ ๊ถ์ ํ์ธํ๊ธฐ ์ํ ์คํฌ๋ฆฝํธ๋ฅผ ํฌํจํ๋ค.
Outputs
- ์ฌ๋ฌ๊ฐ์ ์ถ๋ ฅ์ ๊ฐ์ง ์ ์๋ค.
Locktime
- ํธ๋์ญ์ ์ ์ ํจ๊ธฐ๊ฐ์ ์ค์ ํ๋ค.
- ๋น๋ฒํ ๊ฑฐ๋ ์ํฉ์ ๊ณ ์ํ์ฌ ์ถ๊ฐ๋์๋ค.
Codes
class Tx:
def __init__(self, version, tx_ins, tx_outs, locktime, testnet=False):
self.version = version
self.tx_ins = tx_ins # <1>
self.tx_outs = tx_outs
self.locktime = locktime
self.testnet = testnet # <2>
def __repr__(self):
tx_ins = ''
for tx_in in self.tx_ins:
tx_ins += tx_in.__repr__() + '\n'
tx_outs = ''
for tx_out in self.tx_outs:
tx_outs += tx_out.__repr__() + '\n'
return 'tx: {}\nversion: {}\ntx_ins:\n{}tx_outs:\n{}locktime: {}'.format(
self.id(),
self.version,
tx_ins,
tx_outs,
self.locktime,
)
def id(self): # <3>
'''Human-readable hexadecimal of the transaction hash'''
return self.hash().hex()
def hash(self): # <4>
'''Binary hash of the legacy serialization'''
return hash256(self.serialize())[::-1]
# end::source1[]
@classmethod
def parse(cls, s, testnet=False):
'''
์คํธ๋ฆผ์ ๋ฐ์์ ํธ๋์ญ์
์ ํ์ฑํ๊ณ Tx ๊ฐ์ฒด๋ฅผ ๋ฐํํ๋ค.
'''
# s.read(n) will return n bytes
# ๋ฒ์
# version is an integer in 4 bytes, little-endian
version = little_endian_to_int(s.read(4))
# ์
๋ ฅ
# num_inputs is a varint, use read_varint(s)
num_inputs = read_varint(s)
# parse num_inputs number of TxIns
tx_ins = []
for _ in range(num_inputs):
tx_ins.append(TxIn.parse(s))
# ์ถ๋ ฅ
# num_outputs is a varint, use read_varint(s)
num_outputs = read_varint(s)
# parse num_outputs number of TxOuts
tx_outs = []
for _ in range(num_outputs):
tx_outs.append(TxOut.parse(s))
# ๋กํ์
# locktime is an integer in 4 bytes, little-endian
locktime = little_endian_to_int(s.read(4))
# return an instance of the class (see __init__ for args)
return cls(version, tx_ins, None, None, testnet=testnet)
def serialize(self):
'''Returns the byte serialization of the transaction'''
result = int_to_little_endian(self.version, 4)
result += encode_varint(len(self.tx_ins))
for tx_in in self.tx_ins:
result += tx_in.serialize()
result += encode_varint(len(self.tx_outs))
for tx_out in self.tx_outs:
result += tx_out.serialize()
result += int_to_little_endian(self.locktime, 4)
return result
def fee(self):
'''Returns the fee of this transaction in satoshi'''
# initialize input sum and output sum
input_sum = 0
output_sum = 0
# use TxIn.value() to sum up the input amounts
input_sum = sum([tx_in.value() for tx_in in self.tx_ins])
# use TxOut.amount to sum up the output amounts
output_sum = sum([tx_out.amount for tx_out in self.tx_outs])
# fee is input sum - output sum
fee = input_sum - output_sum
return fee
- ์์๋ฃ ๊ฐ์ ๊ฒฝ์ฐ Transaction์ ๊ตฌ์กฐ๋ฅผ ์ดํดํ ํ์ ๋ค๋ฅธ ๊ธ๋ก ์ ๋ฆฌํ๊ฒ ๋ค.