๋น„ํŠธ์ฝ”์ธ์˜ ํŠธ๋žœ์žญ์…˜์— ๋Œ€ํ•ด ์•Œ์•„๋ณด์ž.

Transaction

  • ์•ž์—์„œ ๋„คํŠธ์›Œํฌ ํ˜น์€ ๋””๋ฐ”์ด์Šค์— ์ด๋™ํ•˜๊ธฐ ์œ„ํ•œ ๊ณต๊ฐœํ‚ค์™€ ๋น„๋ฐ€ํ‚ค์˜ ์ง๋ ฌํ™” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ์•Œ์•„๋ณด์•˜๋‹ค.
  • ๋ฌผ๋ก  ๊ทธ์— ๋Œ€ํ•œ ํŒŒ์‹ฑ๊นŒ์ง€ ๊ฐ™์ด ๋ฐฐ์› ๋‹ค.
  • ํ˜„์žฌ๊นŒ์ง€ ํŠน์ • ๊ฐœ์ธ์ด ์–ผ๋งˆ์˜ ๋น„ํŠธ์ฝ”์ธ์„ ๋ณด๋ƒˆ๋‹ค๋Š” ์‚ฌ์‹ค(๋ฌธ์„œ)์„ ์ฆ๋ช…ํ•  ์ˆ˜ ์žˆ๊ณ  (์„œ๋ช…/๊ฒ€์ฆ ์•Œ๊ณ ๋ฆฌ์ฆ˜)
  • ์ด๋ฅผ ๋„คํŠธ์›Œํฌ์— ํƒœ์›Œ, ๋ถˆํŠน์ • ๋‹ค๋ฅธ ๋…ธ๋“œ๋“ค์ด ์ด ์ •๋ณด๋ฅผ ๋ฐ›์•„ ํ•ด๋…(Decode)ํ•  ์ˆ˜ ์žˆ์Œ์„ ๋ฐฐ์› ๋‹ค.
  • ๊ทธ๋Ÿฐ๋ฐ, โ€œ์–ผ๋งˆ์˜ ๋น„ํŠธ์ฝ”์ธ์„ ๋ณด๋ƒˆ๋‹คโ€๋ผ๋Š” ์‚ฌ์‹ค์— ๋Œ€ํ•ด์„œ๋Š” ์–ด๋–ป๊ฒŒ ๊ตฌ์„ฑ๋˜์—ˆ๋Š”์ง€ ๋ชจ๋ฅธ๋‹ค.
  • ์šฐ๋ฆฌ๋Š” ์ด๋Ÿฌํ•œ ํ˜•ํƒœ์˜ ํ–‰์œ„๋ฅผ ์†Œ์œ„ โ€œ๊ฑฐ๋ž˜โ€๋ผ๋Š” ๋‹จ์–ด๋กœ ์ธ์‹ํ•˜๊ณ  ์žˆ๋‹ค.
  • ๊ทธ๋ ‡๋‹ค๋ฉด ๋น„ํŠธ์ฝ”์ธ์—์„œ์˜ ๊ฑฐ๋ž˜๋Š” ์–ด๋–ค์‹์œผ๋กœ ๊ตฌ์„ฑ๋˜์–ด ์žˆ์„๊นŒ?
  • A, B ๋‘๋ช…์˜ ์‚ฌ๋žŒ์˜ ๊ณ„์ขŒ์— ์ ํžˆ๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋˜์–ด ์žˆ์„๊นŒ?
    • A: ๋ณด๋‚ธ์ด(A), ๋ฐ›๋Š”์ด(B) ๊ธˆ์•ก(30000)
  • ๊ทธ ๊ฑฐ๋ž˜๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š”๋ฐ ์žˆ์–ด ๊ธฐ์ˆ ์ ์ธ ์ œ์•ฝ์€ ์—†๋Š”๊ฐ€? ๊ทธ๊ฑธ ์–ด๋–ป๊ฒŒ ํ•ด๊ฒฐํ• ๊นŒ?
  • ์ด์— ๋Œ€ํ•ด์„œ ์•Œ์•„๋ณด๊ฒ ๋‹ค.

Transaction Components

  1. Version
  2. Inputs
  3. Outputs
  4. 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์˜ ๊ตฌ์กฐ๋ฅผ ์ดํ•ดํ•œ ํ›„์— ๋‹ค๋ฅธ ๊ธ€๋กœ ์ •๋ฆฌํ•˜๊ฒ ๋‹ค.

Reference