Jason Dev
About
멤풀에서 트랜잭션 구출하기
published: 2024-05-12
rbf
cpfp
bitcoind

비트코인 트랜잭션 전송 시 수수료를 낮게 책정해서 해당 트랜잭션이 오랜 시간 블록에 포함되지 않는 경우가 종종 발생한다. 특히 요즘과 같이 오디널스와 같은 이슈로 트랜잭션 수수료가 치솟는 상황에서 자주 발생한다.

트랜잭션이 오랜 시간 대기 상태일 때 사용자의 선택지는 다음과 같다.

  1. 기다리기: 최근 약 2주 간의 수수료를 살펴보고 그 범위 안에 있다면 기다려본다. 오랜 시간이 지나도 트랜잭션이 처리되지 않는다면 해당 트랜잭션은 멤풀에서 삭제된다. 트랜잭션이 멤풀에서 삭제되는 정책은 각 노드마다 다르므로 트랜잭션이 언제 삭제될지는 장담할 수 없다. 참고로 비트코인 코어 최신 버전에서는 2주가 지나면 멤풀에서 삭제된다.
  2. RBF(Replace-by-Fee) 사용하기: 트랜잭션을 보낸 사람이 수수료를 올리는 방법이다.
  3. CPFP(Child-Pays-for-Parent) 사용하기: 트랜잭션에서 비트코인을 받는 사람이 수수료를 올리는 방법이다.

먼저 RBF, CPFP의 개념을 이해하고 각각 bitcoind에서 어떻게 처리할 수 있는지 알아보자.

개념 이해하기

RBF (Replace-by-Fee)

RBF는 트랜잭션을 보낸 사람이 수수료를 올리는 방법이다. 기존에 전송했던 트랜잭션을 조금 수정하고 수수료를 인상해서 네트워크로 전파한다. 채굴자는 수수료가 높은 트랜잭션을 채굴해야 이득이므로 수정된 트랜잭션을 블록에 포함시키고 이전 트랜잭션은 멤풀에서 삭제한다.

RBF에는 몇 가지 종류가 있지만 이 글에서는 주로 opt-in RBF에 대해 설명한다. opt-in RBF는 BIP-125에 명시되어 있으므로 사실상의 표준이라 할 수 있다.

opt-in RBF 활성화하기

opt-in RBF는 트랜잭션마다 활성화 여부를 결정할 수 있으며 활성화 되어 있어야 사용할 수 있다. 트랜잭션 각 입력의 sequence 필드를 통해 opt-in RBF 활성화 여부를 결정할 수 있다.

sequence 값이 0 보다 크고 0xffffffff-1(4294967294) 보다 작다면 opt-in RBF를 사용할 수 있다.

opt-in RBF 조건

이전 트랜잭션의 입력에 사용된 UTXO가 반드시 하나 이상 포함되어야 한다. 그렇지 않으면 다른 트랜잭션으로 인식된다.

만약 이전 트랜잭션의 입력을 사용하지 않고 모두 새로운 UTXO를 사용한다면 수신자에게 같은 금액을 두 번 전송하는 사태가 발생할 수 있다. 따라서 bitcoind를 이용해서 수동으로 opt-in RBF를 사용할 때는 주의가 필요하다.

당연한 얘기지만 이전 트랜잭션이 블록에 포함되면 RBF를 사용할 수 없다. 수신자 입장에서 반드시 트랜잭션 confirmation을 기다려야 하는 이유도 여기에 있다. unconfirmed 트랜잭션은 언제든지 수정 가능하므로 수신자는 반드시 confirmation을 확인하고 거래를 진행해야 한다.

opt-in RBF 비활성화 이유

송신자 입장에서는 opt-in RBF를 활성화해야 유연하므로 장점만 존재한다. 하지만 수신자 입장에서는 opt-in RBF 활성화 시 해당 트랜잭션은 수정 가능하므로 반드시 confirmation을 기다려야 한다. 따라서 빠르게 결제를 확정하기 위해 opt-in RBF를 비활성화할 수 있다.

하지만 Full RBF 등 opt-in RBF 비활성화 상태에서도 여전히 트랜잭션 수정에 대한 가능성이 열려있으므로 opt-in RBF 비활성화 상태라고 하더라도 confirmation을 기다리는 것이 안전하다.

BIP-125 등의 문서는 비트코인 커뮤니티 내에서 장려되는 방식일 뿐이며 어떤 트랜잭션을 블록에 포함시킬지 판단하는 것은 각 채굴자이다. 많은 채굴자가 BIP를 따르고 있지만, 채굴자 입장에서는 단순히 수수료가 높은 트랜잭션을 블록에 포함시키는 것이 이득이며 이를 막을 수 있는 방법은 없다.

CPFP (Child-Pays-for-Parent)

트랜잭션에서 비트코인을 받는 사람이 수수료를 올리는 방법이다. 이전 트랜잭션의 수수료를 높인다는 목적은 RBF와 같지만 CPFP는 이를 실행하는 주체가 다르다.

RBF는 이전 트랜잭션을 수정하는 방식이므로 기존 수수료에 추가되는 수수료만 지불하면 된다. 하지만 CPFP는 이전 트랜잭션은 그대로 두고 새로운 트랜잭션을 만들어서 함께 블록에 포함시키는 방식이므로 두 트랜잭션 수수료를 모두 지불하게 된다.

예를 들어, A 사용자가 B 사용자에게 보내는 a 트랜잭션을 만들었고 수수료로 10 sats를 설정했다고 가정해보자. 현재 시점 적정 수수료는 30 sats라고 하면 20 sats가 부족하다. B 사용자는 트랜잭션 처리를 빠르게 하기 위해 a 트랜잭션의 output을 다른 주소로 보내는 b 트랜잭션을 만든다. b 트랜잭션은 수수료로 60sats를 설정하는데, 이는 적정 수수료보다 30 sats가 초과된 금액이다. 이 초과된 금액은 a 트랜잭션의 수수료를 올리기 위한 것이며 여기서 b 트랜잭션이 CPFP을 활용한 것이다. 채굴자는 적정 수수료보다 많은 수수료를 받을 수 있으므로 a, b 트랜잭션 모두를 블록에 포함시키게 된다. (b 트랜잭션만 포함시킬 수는 없다)

CPFP에서 새로운 트랜잭션은 반드시 이전 트랜잭션의 출력을 입력으로 사용해야 한다. CPFP는 BIP로 정의된 스펙은 아니지만 채굴자에게 이득이 되는 방식이므로 많은 채굴자가 처리를 해준다.

모든 지갑 소프트웨어가 CPFP를 지원하지는 않는다. 참고로 sparrow 월렛에서는 지원하고 있다.

bitcoind에서 RBF/CPFP 사용하기

사전 준비

초기 설정은 이전 글에서 다룬 내용을 참고하자.

이번 글에서도 로컬에서 비트코인 노드 2개를 띄운 상태를 가정한다. 아래와 같이 각 노드에서 편하게 명령어를 실행해보기 위해 별칭을 등록하자.

alias bc1="bitcoin-cli -rpcuser=w1 -rpcpassword=w1 -rpcport=1111"
alias bc2="bitcoin-cli -rpcuser=w2 -rpcpassword=w2 -rpcport=2222"

RBF

bc1에서 bc2로 비트코인을 보내고 해당 트랜잭션의 수수료를 올려보자.

먼저 bc2의 주소를 확인한다.

bc2 getnewaddress
bcrt1qvjj6l3utla80y9u7s4qdturuawltqp3pwt07pq

bc1의 UTXO를 확인해보고 이어서 트랜잭션을 생성한다.

bc1 listunspent
[
{
"txid": "033129c3e660abe2ee6a36cb054751a94aab048668f157e179b982036b51e990",
"vout": 1,
"address": "bcrt1qapa7cg05evn2ynn4522slcjraxvx30gz0uz8qz",
"scriptPubKey": "0014e87bec21f4cb26a24e75a2950fe243e99868bd02",
"amount": 0.05827180,
"confirmations": 1,
"spendable": true,
"solvable": true,
"desc": "wpkh([bd28eb6d/84'/1'/0'/1/9]02d09342168e257c8645e3c601b8f3bdce22db64ee616fb7300a2aa92ffe8c7914)#x4dtx4ac",
"parent_descs": [
"wpkh(tpubD6NzVbkrYhZ4Xq9mJeQj9Y7vgT2nmsY8HnsaGR28ffjPFpopZ3wnntnMNhQ5LvDWjFqduoWqrMs8VuMJTdTV6vHGS7jVzMYo4JwZfGuz14K/84'/1'/0'/1/*)#mmhnk5cr"
],
"safe": true
}
]
bc1 sendtoaddress bcrt1qvjj6l3utla80y9u7s4qdturuawltqp3pwt07pq 0.01
3a32cd08bbd39d07a6d54a869843970897c762ba05794313d797a5c581c434f9

gettransaction 명령어로 트랜잭션 정보를 확인한다.

bc1 gettransaction 3a32cd08bbd39d07a6d54a869843970897c762ba05794313d797a5c581c434f9
{
"amount": -0.01000000,
"fee": -0.00002820,
"confirmations": 0,
"trusted": true,
"txid": "3a32cd08bbd39d07a6d54a869843970897c762ba05794313d797a5c581c434f9",
"wtxid": "525c9b8059b3eb39adaf649f0b0bfaa55bdc56d940112b978b1e5c2748dbebb2",
"walletconflicts": [
],
"time": 1705703202,
"timereceived": 1705703202,
"bip125-replaceable": "yes",
"details": [
{
"address": "bcrt1qvjj6l3utla80y9u7s4qdturuawltqp3pwt07pq",
"category": "send",
"amount": -0.01000000,
"vout": 1,
"fee": -0.00002820,
"abandoned": false
}
],
"hex": "0200000000010190e9516b0382b979e157f1688604ab4aa9514705cb366aeee2ab60e6c32931030100000000fdffffff02289d49000000000016001416b42624d6ae3054b733a9fbf8aa65f8002a876d40420f000000000016001464a5afc78bff4ef2179e8540d5f07cebbeb006210247304402203d03aeb4b0f1ccaa08cee0d606da3dd33e90f734faa70921dbae3112ee12856c022005057d5ff2e9e45f5377406431daf4c3481d0832a6fbf22d34139113a0fb95d7012102d09342168e257c8645e3c601b8f3bdce22db64ee616fb7300a2aa92ffe8c791400000000"
}

bip125-replaceable 필드를 통해 opt-in RBF가 활성화 되어 있는 것을 확인할 수 있다. 따로 설정을 하지 않으면 sendtoaddress 명령어가 opt-in RBF를 활성화 한다는 것을 알 수 있다.

decoderawtransaction 명령어를 이용해서 트랜잭션의 세부 정보를 확인해보자.

bc1 decoderawtransaction 0200000000010190e9516b0382b979e157f1688604ab4aa9514705cb366aeee2ab60e6c32931030100000000fdffffff02289d49000000000016001416b42624d6ae3054b733a9fbf8aa65f8002a876d40420f000000000016001464a5afc78bff4ef2179e8540d5f07cebbeb006210247304402203d03aeb4b0f1ccaa08cee0d606da3dd33e90f734faa70921dbae3112ee12856c022005057d5ff2e9e45f5377406431daf4c3481d0832a6fbf22d34139113a0fb95d7012102d09342168e257c8645e3c601b8f3bdce22db64ee616fb7300a2aa92ffe8c791400000000
{
"txid": "3a32cd08bbd39d07a6d54a869843970897c762ba05794313d797a5c581c434f9",
"hash": "525c9b8059b3eb39adaf649f0b0bfaa55bdc56d940112b978b1e5c2748dbebb2",
"version": 2,
"size": 222,
"vsize": 141,
"weight": 561,
"locktime": 0,
"vin": [
{
"txid": "033129c3e660abe2ee6a36cb054751a94aab048668f157e179b982036b51e990",
"vout": 1,
"scriptSig": {
"asm": "",
"hex": ""
},
"txinwitness": [
"304402203d03aeb4b0f1ccaa08cee0d606da3dd33e90f734faa70921dbae3112ee12856c022005057d5ff2e9e45f5377406431daf4c3481d0832a6fbf22d34139113a0fb95d701",
"02d09342168e257c8645e3c601b8f3bdce22db64ee616fb7300a2aa92ffe8c7914"
],
"sequence": 4294967293
}
],
"vout": [
{
"value": 0.04824360,
"n": 0,
"scriptPubKey": {
"asm": "0 16b42624d6ae3054b733a9fbf8aa65f8002a876d",
"desc": "addr(bcrt1qz66zvfxk4cc9fden48al32n9lqqz4pmdfyr6h6)#wnz82trs",
"hex": "001416b42624d6ae3054b733a9fbf8aa65f8002a876d",
"address": "bcrt1qz66zvfxk4cc9fden48al32n9lqqz4pmdfyr6h6",
"type": "witness_v0_keyhash"
}
},
{
"value": 0.01000000,
"n": 1,
"scriptPubKey": {
"asm": "0 64a5afc78bff4ef2179e8540d5f07cebbeb00621",
"desc": "addr(bcrt1qvjj6l3utla80y9u7s4qdturuawltqp3pwt07pq)#qh829hqq",
"hex": "001464a5afc78bff4ef2179e8540d5f07cebbeb00621",
"address": "bcrt1qvjj6l3utla80y9u7s4qdturuawltqp3pwt07pq",
"type": "witness_v0_keyhash"
}
}
]
}

입력의 sequence 필드가 4294967293이므로 0xffffffff-1(4294967294) 보다 작다. 따라서 opt-in RBF가 활성화 되어 있다는 것을 다시 한 번 확인할 수 있다.

이제 RBF를 이용해서 이전 트랜잭션의 수수료를 올리는 트랜잭션을 생성해보자.

쉬운 방법: bumpfee

bumpfee 명령어를 이용하면 쉽게 RBF 트랜잭션을 생성할 수 있다.

bc1 getrawmempool
[
"3a32cd08bbd39d07a6d54a869843970897c762ba05794313d797a5c581c434f9"
]
bc1 bumpfee 3a32cd08bbd39d07a6d54a869843970897c762ba05794313d797a5c581c434f9
{
"txid": "98f6ad37b2fe13e403ef2842cb3fdcae2887d0f1b32fb9e7c566779a269eab7b",
"origfee": 0.00002820,
"fee": 0.00003526,
"errors": [
]
}
bc1 getrawmempool
[
"98f6ad37b2fe13e403ef2842cb3fdcae2887d0f1b32fb9e7c566779a269eab7b"
]

수수료가 2,820 sats에서 3,526 sats로 변경되었다.

getrawmempool 명령어를 통해 이전 트랜잭션이 멤풀에서 삭제되고 수수료를 인상한 트랜잭션만 남았다는 것을 알 수 있다.

fee_rate 옵션을 사용하면 원하는 수수료율를 직접 입력할 수 있다. fee_rate의 단위는 sat/vB이며 vB는 decoderawtransaction 결과의 vsize 필드에서 확인할 수 있다. 하지만 vsize 대신 weight 필드를 사용하는 것이 좀 더 정확하다.

sat/vB = sat/(weight/4)

위 decoderawtransaction 결과에서 이전 트랜잭션의 weight는 561이므로 수수료와 함께 계산하면 이전 트랜잭션의 fee_rate는 다음과 같다.

  • 이전 트랜잭션의 fee_rate: 2820/(561/4) = 20.10 sat/vB
  • 신규 트랜잭션의 fee_rate: 3526/(561/4) = 25.14 sat/vB

다음과 같이 fee_rate 옵션을 이용해서 40 sat/vB 수수료율을 갖는 새로운 트랜잭션을 생성할 수 있다.

bc1 bumpfee 98f6ad37b2fe13e403ef2842cb3fdcae2887d0f1b32fb9e7c566779a269eab7b '{"fee_rate": 40}'
{
"txid": "fe1da575fce9ecfc8c6560c38990d389fdec615530cf5539adace2f16deca170",
"origfee": 0.00003526,
"fee": 0.00005640,
"errors": [
]
}

복잡한 방법: createrawtransaction

마지막에 생성한 트랜잭션의 세부 내용을 확인해보자.

bc1 getrawtransaction fe1da575fce9ecfc8c6560c38990d389fdec615530cf5539adace2f16deca170 true
{
"txid": "fe1da575fce9ecfc8c6560c38990d389fdec615530cf5539adace2f16deca170",
"hash": "362bfe153fd184e8cb1e84b171879a3c0c3eee0dcd84e273b49781d11d78d5ef",
"version": 2,
"size": 222,
"vsize": 141,
"weight": 561,
"locktime": 0,
"vin": [
{
"txid": "033129c3e660abe2ee6a36cb054751a94aab048668f157e179b982036b51e990",
"vout": 1,
"scriptSig": {
"asm": "",
"hex": ""
},
"txinwitness": [
"304402207dba28fc9bc88b6273eb89259f7a4a864a43eeb1a73f90120c92a1ca4ad1c886022036b8a30f1326560d1516e0d5532abc86ac8934a1313245934dc759416abd7e3101",
"02d09342168e257c8645e3c601b8f3bdce22db64ee616fb7300a2aa92ffe8c7914"
],
"sequence": 4294967293
}
],
"vout": [
{
"value": 0.04821540,
"n": 0,
"scriptPubKey": {
"asm": "0 16b42624d6ae3054b733a9fbf8aa65f8002a876d",
"desc": "addr(bcrt1qz66zvfxk4cc9fden48al32n9lqqz4pmdfyr6h6)#wnz82trs",
"hex": "001416b42624d6ae3054b733a9fbf8aa65f8002a876d",
"address": "bcrt1qz66zvfxk4cc9fden48al32n9lqqz4pmdfyr6h6",
"type": "witness_v0_keyhash"
}
},
{
"value": 0.01000000,
"n": 1,
"scriptPubKey": {
"asm": "0 64a5afc78bff4ef2179e8540d5f07cebbeb00621",
"desc": "addr(bcrt1qvjj6l3utla80y9u7s4qdturuawltqp3pwt07pq)#qh829hqq",
"hex": "001464a5afc78bff4ef2179e8540d5f07cebbeb00621",
"address": "bcrt1qvjj6l3utla80y9u7s4qdturuawltqp3pwt07pq",
"type": "witness_v0_keyhash"
}
}
],
"hex": "0200000000010190e9516b0382b979e157f1688604ab4aa9514705cb366aeee2ab60e6c32931030100000000fdffffff02249249000000000016001416b42624d6ae3054b733a9fbf8aa65f8002a876d40420f000000000016001464a5afc78bff4ef2179e8540d5f07cebbeb006210247304402207dba28fc9bc88b6273eb89259f7a4a864a43eeb1a73f90120c92a1ca4ad1c886022036b8a30f1326560d1516e0d5532abc86ac8934a1313245934dc759416abd7e31012102d09342168e257c8645e3c601b8f3bdce22db64ee616fb7300a2aa92ffe8c791400000000"
}

이제 createrawtransaction 명령어를 이용해서 RBF 트랜잭션을 생성해보자. 입력과 출력을 거의 그대로 입력하고 잔돈의 수량만 조절해서 수수료를 높이자.

bc1 -named createrawtransaction inputs='''[ { "txid": "033129c3e660abe2ee6a36cb054751a94aab048668f157e179b982036b51e990", "vout": 1 } ]''' outputs='''{ "bcrt1qz66zvfxk4cc9fden48al32n9lqqz4pmdfyr6h6": 0.04, "bcrt1qvjj6l3utla80y9u7s4qdturuawltqp3pwt07pq": 0.01 }'''
020000000190e9516b0382b979e157f1688604ab4aa9514705cb366aeee2ab60e6c32931030100000000fdffffff0200093d000000000016001416b42624d6ae3054b733a9fbf8aa65f8002a876d40420f000000000016001464a5afc78bff4ef2179e8540d5f07cebbeb0062100000000
bc1 signrawtransactionwithwallet 020000000190e9516b0382b979e157f1688604ab4aa9514705cb366aeee2ab60e6c32931030100000000fdffffff0200093d000000000016001416b42624d6ae3054b733a9fbf8aa65f8002a876d40420f000000000016001464a5afc78bff4ef2179e8540d5f07cebbeb0062100000000
{
"hex": "0200000000010190e9516b0382b979e157f1688604ab4aa9514705cb366aeee2ab60e6c32931030100000000fdffffff0200093d000000000016001416b42624d6ae3054b733a9fbf8aa65f8002a876d40420f000000000016001464a5afc78bff4ef2179e8540d5f07cebbeb0062102473044022013086117f728d5285c6b0eb2266d7a144c78f6cd38d51fa2c2ec159773e8794b02200fdb3f5e2fa6a22c8d5b622d38a8ceada040ea0f67a6373b760a1ca7405fe2d8012102d09342168e257c8645e3c601b8f3bdce22db64ee616fb7300a2aa92ffe8c791400000000",
"complete": true
}
bc1 sendrawtransaction 0200000000010190e9516b0382b979e157f1688604ab4aa9514705cb366aeee2ab60e6c32931030100000000fdffffff0200093d000000000016001416b42624d6ae3054b733a9fbf8aa65f8002a876d40420f000000000016001464a5afc78bff4ef2179e8540d5f07cebbeb0062102473044022013086117f728d5285c6b0eb2266d7a144c78f6cd38d51fa2c2ec159773e8794b02200fdb3f5e2fa6a22c8d5b622d38a8ceada040ea0f67a6373b760a1ca7405fe2d8012102d09342168e257c8645e3c601b8f3bdce22db64ee616fb7300a2aa92ffe8c791400000000
c4126af6a51e8b7702993f07f15135a6f44902345b1eb2f0dc0499b0017432b1

잔돈 0.04821540를 0.04로 변경하면서 수수료를 821,540 sat 만큼 올렸다.

멤풀에 잘 등록되었는지 확인해보자.

bc1 getrawmempool
[
"c4126af6a51e8b7702993f07f15135a6f44902345b1eb2f0dc0499b0017432b1"
]

CPFP

먼저 부모 트랜잭션을 생성한다.

bc2 getnewaddress
bcrt1qydg0d7rrwasas3xry3gn2tes4wha2yetd3dedn
bc1 sendtoaddress bcrt1qydg0d7rrwasas3xry3gn2tes4wha2yetd3dedn 0.01
68faa557bc1b978ef984d5fd587d0af286d334db5caf4fc1026db666e1385c30

gettransaction 명령어로 수수료를 확인해보자.

bc1 gettransaction 68faa557bc1b978ef984d5fd587d0af286d334db5caf4fc1026db666e1385c30
{
"amount": -0.01000000,
"fee": -0.00002820,
"confirmations": 0,
"trusted": true,
"txid": "68faa557bc1b978ef984d5fd587d0af286d334db5caf4fc1026db666e1385c30",
"wtxid": "5bf37e8f9aec3da58b55796a382e2c61ba48e71d2c4f0d3645bd8961bb67399b",
"walletconflicts": [
],
"time": 1705727611,
"timereceived": 1705727611,
"bip125-replaceable": "yes",
"details": [
{
"address": "bcrt1qydg0d7rrwasas3xry3gn2tes4wha2yetd3dedn",
"category": "send",
"amount": -0.01000000,
"vout": 1,
"fee": -0.00002820,
"abandoned": false
}
],
"hex": "02000000000101b1327401b09904dcf0b21e5b340249f4a63551f1073f9902778b1ea5f66a12c40000000000fdffffff02bcbb2d0000000000160014e7f0601ce7895e93231eefc8572cc35e9d54159f40420f00000000001600142350f6f8637761d844c32451352f30abafd5132b0247304402206570bea3ede3e7ea908928092e0f777326cfece537f639fdb88a4a04e18a608b022057a597dd044d650ad65f106eb909b7e007e77c8c9b996688f97edce04ae99d69012102b62c773056d1d58dbe1c840a81b21990ab8cabdc57d42826ba29852b28ae7119f6000000"
}

수수료가 2,820 sats라는 것을 확인했다.

출력 인덱스 번호를 확인하기 위해 getrawtransaction 명령어를 실행하자.

bc1 getrawtransaction 68faa557bc1b978ef984d5fd587d0af286d334db5caf4fc1026db666e1385c30 true
{
"txid": "68faa557bc1b978ef984d5fd587d0af286d334db5caf4fc1026db666e1385c30",
"hash": "5bf37e8f9aec3da58b55796a382e2c61ba48e71d2c4f0d3645bd8961bb67399b",
"version": 2,
"size": 222,
"vsize": 141,
"weight": 561,
"locktime": 246,
"vin": [
{
"txid": "c4126af6a51e8b7702993f07f15135a6f44902345b1eb2f0dc0499b0017432b1",
"vout": 0,
"scriptSig": {
"asm": "",
"hex": ""
},
"txinwitness": [
"304402206570bea3ede3e7ea908928092e0f777326cfece537f639fdb88a4a04e18a608b022057a597dd044d650ad65f106eb909b7e007e77c8c9b996688f97edce04ae99d6901",
"02b62c773056d1d58dbe1c840a81b21990ab8cabdc57d42826ba29852b28ae7119"
],
"sequence": 4294967293
}
],
"vout": [
{
"value": 0.02997180,
"n": 0,
"scriptPubKey": {
"asm": "0 e7f0601ce7895e93231eefc8572cc35e9d54159f",
"desc": "addr(bcrt1qulcxq888390fxgc7aly9wtxrt6w4g9vlphjlhc)#lp0f7pg7",
"hex": "0014e7f0601ce7895e93231eefc8572cc35e9d54159f",
"address": "bcrt1qulcxq888390fxgc7aly9wtxrt6w4g9vlphjlhc",
"type": "witness_v0_keyhash"
}
},
{
"value": 0.01000000,
"n": 1,
"scriptPubKey": {
"asm": "0 2350f6f8637761d844c32451352f30abafd5132b",
"desc": "addr(bcrt1qydg0d7rrwasas3xry3gn2tes4wha2yetd3dedn)#7gutalnx",
"hex": "00142350f6f8637761d844c32451352f30abafd5132b",
"address": "bcrt1qydg0d7rrwasas3xry3gn2tes4wha2yetd3dedn",
"type": "witness_v0_keyhash"
}
}
],
"hex": "02000000000101b1327401b09904dcf0b21e5b340249f4a63551f1073f9902778b1ea5f66a12c40000000000fdffffff02bcbb2d0000000000160014e7f0601ce7895e93231eefc8572cc35e9d54159f40420f00000000001600142350f6f8637761d844c32451352f30abafd5132b0247304402206570bea3ede3e7ea908928092e0f777326cfece537f639fdb88a4a04e18a608b022057a597dd044d650ad65f106eb909b7e007e77c8c9b996688f97edce04ae99d69012102b62c773056d1d58dbe1c840a81b21990ab8cabdc57d42826ba29852b28ae7119f6000000"
}

1번 출력에서 bc2의 주소를 확인할 수 있다.

현재 평균 수수료를 5,000 sats라고 가정하면 2,180(5000-2820) sats가 추가로 필요하다. 이를 위해 7,180(5000+2180) sats를 새로운 트랜잭션의 수수료로 결정하자.

bc2 자신에게 보내는 트랜잭션을 생성하자.

bc2 getnewaddress
bcrt1q4yvcj2fz3jk3ehac5atg0hrhvw5u4zf5rsg770

bc2 -named createrawtransaction inputs='''[ { "txid": "68faa557bc1b978ef984d5fd587d0af286d334db5caf4fc1026db666e1385c30", "vout": 1 } ]''' outputs='''{ "bcrt1q4yvcj2fz3jk3ehac5atg0hrhvw5u4zf5rsg770": 0.00992820 }'''
0200000001305c38e166b66d02c14faf5cdb34d386f20a7d58fdd584f98e971bbc57a5fa680100000000fdffffff0134260f0000000000160014a9198929228cad1cdfb8a75687dc7763a9ca893400000000
bc2 signrawtransactionwithwallet 0200000001305c38e166b66d02c14faf5cdb34d386f20a7d58fdd584f98e971bbc57a5fa680100000000fdffffff0134260f0000000000160014a9198929228cad1cdfb8a75687dc7763a9ca893400000000
{
"hex": "02000000000101305c38e166b66d02c14faf5cdb34d386f20a7d58fdd584f98e971bbc57a5fa680100000000fdffffff0134260f0000000000160014a9198929228cad1cdfb8a75687dc7763a9ca89340247304402200477e4bd3838e81c7ee7eca6dae15bba98f5412e23899ca1bfe37ddac7e9f59202202c5126eabda6937e3f5cfe8c649366f3b0bff4646e55e0e7444f8a0defa61bac0121029892266dbe5047ac52cd46a8c5e25d75be0ff2e96b5cd337e3b227cfdb4fd34a00000000",
"complete": true
}
bc2 sendrawtransaction 02000000000101305c38e166b66d02c14faf5cdb34d386f20a7d58fdd584f98e971bbc57a5fa680100000000fdffffff0134260f0000000000160014a9198929228cad1cdfb8a75687dc7763a9ca89340247304402200477e4bd3838e81c7ee7eca6dae15bba98f5412e23899ca1bfe37ddac7e9f59202202c5126eabda6937e3f5cfe8c649366f3b0bff4646e55e0e7444f8a0defa61bac0121029892266dbe5047ac52cd46a8c5e25d75be0ff2e96b5cd337e3b227cfdb4fd34a00000000
b346256b877b6d8750d0fa924be32915a5fbd04a78424a3cc823f5f3d757436c

입력은 0.01 BTC 이므로 수수료를 7,180 sats로 설정하기 위해 0.00992820 BTC를 입력했다.

0.00992820 = 0.01 - 0.00007180

이제 채굴을 진행해보자.

bc2 getrawmempool
[
"68faa557bc1b978ef984d5fd587d0af286d334db5caf4fc1026db666e1385c30",
"b346256b877b6d8750d0fa924be32915a5fbd04a78424a3cc823f5f3d757436c"
]
bc2 -generate 1
{
"address": "bcrt1qav3f9chxdsmr964wxl5ew7l9ngypve855qkpx4",
"blocks": [
"23da92aac351f112d6312bd2f81d82237426e2373b2975728099a0d80a9513a6"
]
}
bc2 getrawmempool
[
]

두 개의 트랜잭션이 동시에 블록에 포함된 것을 확인할 수 있다.

보낸 사람이 CPFP 사용하기

보통은 잔돈 때문에 보낸 사람의 UTXO도 부모 트랜잭션의 출력에 존재한다. 따라서 보낸 사람도 자신의 출력을 이용해서 CPFP를 활용할 수 있다. 하지만 두 개의 트랜잭션 수수료를 모두 지불해야 한다는 단점은 존재한다.

부모 트랜잭션을 생성한다.

bc2 getnewaddress
bcrt1qua27ges5aknpurg9dyudpkdsryjmcylmzpdw7g
bc1 sendtoaddress bcrt1qua27ges5aknpurg9dyudpkdsryjmcylmzpdw7g 0.01
571b97caf35074ab2e2feab2fca474b2d39396779fbc65922668eca663f36acf

출력에서 보낸 사람의 잔돈이 있는지 확인해보자.

bc1 getrawtransaction 571b97caf35074ab2e2feab2fca474b2d39396779fbc65922668eca663f36acf true
{
"txid": "571b97caf35074ab2e2feab2fca474b2d39396779fbc65922668eca663f36acf",
"hash": "151ad094d54a6723425c003a33f743357f95d5513c94d3ac110019494efd39d1",
"version": 2,
"size": 222,
"vsize": 141,
"weight": 561,
"locktime": 247,
"vin": [
{
"txid": "68faa557bc1b978ef984d5fd587d0af286d334db5caf4fc1026db666e1385c30",
"vout": 0,
"scriptSig": {
"asm": "",
"hex": ""
},
"txinwitness": [
"3044022044b06ca873aa8a365e5df930c032b252e852c2b131d7c6734a95cdcb4970c1a00220192ee8a6e5c2e2925cae2c647d5453c499dbac0f335c07aeb39df9637d37839f01",
"03f890bf79654bed856534cfe0c47d52b7f825be4d8c82e596ed4d754690e11033"
],
"sequence": 4294967293
}
],
"vout": [
{
"value": 0.01000000,
"n": 0,
"scriptPubKey": {
"asm": "0 e755e46614eda61e0d056938d0d9b01925bc13fb",
"desc": "addr(bcrt1qua27ges5aknpurg9dyudpkdsryjmcylmzpdw7g)#2ed5u50s",
"hex": "0014e755e46614eda61e0d056938d0d9b01925bc13fb",
"address": "bcrt1qua27ges5aknpurg9dyudpkdsryjmcylmzpdw7g",
"type": "witness_v0_keyhash"
}
},
{
"value": 0.01994360,
"n": 1,
"scriptPubKey": {
"asm": "0 88e5f3850b4f0728b86922552dc029f4a0f37f90",
"desc": "addr(bcrt1q3rjl8pgtfurj3wrfyf2jmspf7js0xlusvam423)#urnvfkfs",
"hex": "001488e5f3850b4f0728b86922552dc029f4a0f37f90",
"address": "bcrt1q3rjl8pgtfurj3wrfyf2jmspf7js0xlusvam423",
"type": "witness_v0_keyhash"
}
}
],
"hex": "02000000000101305c38e166b66d02c14faf5cdb34d386f20a7d58fdd584f98e971bbc57a5fa680000000000fdffffff0240420f0000000000160014e755e46614eda61e0d056938d0d9b01925bc13fb786e1e000000000016001488e5f3850b4f0728b86922552dc029f4a0f37f9002473044022044b06ca873aa8a365e5df930c032b252e852c2b131d7c6734a95cdcb4970c1a00220192ee8a6e5c2e2925cae2c647d5453c499dbac0f335c07aeb39df9637d37839f012103f890bf79654bed856534cfe0c47d52b7f825be4d8c82e596ed4d754690e11033f7000000"
}

1번 출력에서 잔돈을 확인할 수 있다.

getaddressinfo 명령어로 내 주소가 맞는지 한 번 더 확인해보자.

bc1 getaddressinfo bcrt1q3rjl8pgtfurj3wrfyf2jmspf7js0xlusvam423
{
"address": "bcrt1q3rjl8pgtfurj3wrfyf2jmspf7js0xlusvam423",
"scriptPubKey": "001488e5f3850b4f0728b86922552dc029f4a0f37f90",
"'ismine'": true,
"solvable": true,
"desc": "wpkh([bd28eb6d/84'/1'/0'/1/13]0216c73479c10c6068edaa56a175f2b32fdd21496959f1e60cffb0c9e0143d06f7)#77c875f2",
"parent_desc": "wpkh([bd28eb6d/84'/1'/0']tpubDD3E21w6xwRSU4AbQ9vdJddZ3YzVsMP5CEyk4pX1wi7NAV3QEdsQ4Fy3GELEzFeX7wSCAkJAHTP7xf2uyR3mpaCy72fWHxnfhMDvmm5Jnx4/1/*)#jm4uyqn6",
"iswatchonly": false,
"isscript": false,
"iswitness": true,
"witness_version": 0,
"witness_program": "88e5f3850b4f0728b86922552dc029f4a0f37f90",
"pubkey": "0216c73479c10c6068edaa56a175f2b32fdd21496959f1e60cffb0c9e0143d06f7",
"ischange": true,
"timestamp": 1704524798,
"hdkeypath": "m/84'/1'/0'/1/13",
"hdseedid": "0000000000000000000000000000000000000000",
"hdmasterfingerprint": "bd28eb6d",
"labels": [
]
}

ismine 필드를 통해 내 주소가 맞다는 것을 알 수 있다.

새로운 트랜잭션의 수수료를 4,360 sats로 하는 트랜잭션을 생성하자.

bc1 getnewaddress
bcrt1qfrrprdvhmz7gdvn9jv9knlc7q6ext0st24xqfj
bc1 -named createrawtransaction inputs='''[ { "txid": "571b97caf35074ab2e2feab2fca474b2d39396779fbc65922668eca663f36acf", "vout": 1 } ]''' outputs='''{ "bcrt1qfrrprdvhmz7gdvn9jv9knlc7q6ext0st24xqfj": 0.0199 }'''
0200000001cf6af363a6ec68269265bc9f779693d3b274a4fcb2ea2f2eab7450f3ca971b570100000000fdffffff01705d1e000000000016001448c611b597d8bc86b265930b69ff1e06b265be0b00000000
bc1 signrawtransactionwithwallet 0200000001cf6af363a6ec68269265bc9f779693d3b274a4fcb2ea2f2eab7450f3ca971b570100000000fdffffff01705d1e000000000016001448c611b597d8bc86b265930b69ff1e06b265be0b00000000
{
"hex": "02000000000101cf6af363a6ec68269265bc9f779693d3b274a4fcb2ea2f2eab7450f3ca971b570100000000fdffffff01705d1e000000000016001448c611b597d8bc86b265930b69ff1e06b265be0b02473044022063bfa037a45c0554bec7e222c166b00e0990feb02b6e42bdd05eb91d20a2142602202d40c3041ed9794329bdb7d2add533595eb918fd343db4c18f8e118f2002b5b101210216c73479c10c6068edaa56a175f2b32fdd21496959f1e60cffb0c9e0143d06f700000000",
"complete": true
}
bc1 sendrawtransaction 02000000000101cf6af363a6ec68269265bc9f779693d3b274a4fcb2ea2f2eab7450f3ca971b570100000000fdffffff01705d1e000000000016001448c611b597d8bc86b265930b69ff1e06b265be0b02473044022063bfa037a45c0554bec7e222c166b00e0990feb02b6e42bdd05eb91d20a2142602202d40c3041ed9794329bdb7d2add533595eb918fd343db4c18f8e118f2002b5b101210216c73479c10c6068edaa56a175f2b32fdd21496959f1e60cffb0c9e0143d06f700000000
bea6d52f27c1fc0a2f1e4cf42f9a492ba507d4150d40377ad4a7c13de100f91b

채굴을 통해 두 트랜잭션이 동시에 처리되는 것을 확인해보자.

bc1 getrawmempool
[
"571b97caf35074ab2e2feab2fca474b2d39396779fbc65922668eca663f36acf",
"bea6d52f27c1fc0a2f1e4cf42f9a492ba507d4150d40377ad4a7c13de100f91b"
]
bc2 -generate 1
{
"address": "bcrt1qzlh9h7ry5h8d43nlsadz8uuna3fwmnys3zlys3",
"blocks": [
"321f1f4dcaed0e55b3b1010bf12d64551c9bf555319738b3ab6bb3238b0702ea"
]
}
bc1 getrawmempool
[
]

Accelerator 이용하기

RBF/CPFP 외에도 비트코인 채굴자들이 제공하는 Accelerator 서비스를 사용할 수도 있다. Accelerator 서비스에 트랜잭션 ID와 함께 일정 금액을 지불하면 마치 RBF로 추가 수수료를 지불한 것과 비슷한 효과를 낼 수 있다. 채굴자는 실제 비트코인 트랜잭션에서 해당 트랜잭션이 지불하는 수수료에 Accelerator 서비스에서 추가로 받은 금액을 더해서 총 수수료를 계산한다. 이 서비스는 RBF/CPFP 기능을 사용하기 힘든 경우에 사용하기 좋다.

다양한 Accelerator 서비스가 있는데 아래는 antpool의 Accelerator 서비스다.

트랜잭션 ID를 입력하면 아래와 같은 화면이 나오는데, 출력되는 비용을 USDT로 지불하면 된다.

댓글 삭제 시 메일 주소가 필요합니다