-
Notifications
You must be signed in to change notification settings - Fork 285
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix CPFP when tx fee is less than MIN_RELAY #694
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,6 +9,7 @@ const Mempool = require('../lib/mempool/mempool'); | |
const Miner = require('../lib/mining/miner'); | ||
const Address = require('../lib/primitives/address'); | ||
const MTX = require('../lib/primitives/mtx'); | ||
const Coin = require('../lib/primitives/coin'); | ||
const MemWallet = require('./util/memwallet'); | ||
const {BufferSet} = require('buffer-map'); | ||
|
||
|
@@ -77,6 +78,7 @@ describe('Miner', function() { | |
|
||
let walletAddr; | ||
const txids = new BufferSet(); | ||
let coin, parentTX; | ||
|
||
it('should generate 20 blocks to wallet address', async () => { | ||
walletAddr = wallet.createReceive().getAddress(); | ||
|
@@ -110,7 +112,6 @@ describe('Miner', function() { | |
} | ||
|
||
assert.strictEqual(mempool.map.size, 10); | ||
|
||
const block = await miner.mineBlock(chain.tip, addr); | ||
await chain.add(block); | ||
|
||
|
@@ -180,4 +181,81 @@ describe('Miner', function() { | |
assert(txids.has(block.txs[i].hash())); | ||
} | ||
}); | ||
|
||
it('should not include free transaction in a block', async () => { | ||
// Miner does not have any room for free TXs | ||
miner.options.minWeight = 0; | ||
|
||
const value = 1 * 1e6; | ||
const fee = 0; | ||
|
||
// Get a change address | ||
const change = wallet.createChange().getAddress(); | ||
const mtx = new MTX(); | ||
coin = wallet.getCoins()[0]; | ||
mtx.addCoin(coin); | ||
mtx.addOutput(addr, value); | ||
mtx.addOutput(change, coin.value - value - fee); // no fee | ||
wallet.sign(mtx); | ||
parentTX = mtx.toTX(); | ||
|
||
await mempool.addTX(parentTX, -1); | ||
assert.strictEqual(mempool.map.size, 1); | ||
|
||
const block = await miner.mineBlock(chain.tip, addr); | ||
await chain.add(block); | ||
|
||
// TX is still in mempool, nothing in block except coinbase | ||
assert.strictEqual(mempool.map.size, 1); | ||
assert.strictEqual(block.txs.length, 1); | ||
}); | ||
|
||
it('should fail to double spend the coin - duplicate tx in mempool', async () => { | ||
const value = 1 * 1e6; | ||
const fee = 1000; | ||
const mtx = new MTX(); | ||
|
||
const change = wallet.createChange().getAddress(); | ||
mtx.addCoin(coin); | ||
mtx.addOutput(addr, value); | ||
mtx.addOutput(change, coin.value - value - fee); | ||
wallet.sign(mtx); | ||
const tx = mtx.toTX(); | ||
|
||
assert.rejects( | ||
async () => await mempool.addTX(tx, -1), | ||
{ | ||
code: 'duplicate', | ||
reason: 'bad-txns-inputs-spent' | ||
} | ||
); | ||
// orignal tx is still in mempool | ||
assert.strictEqual(mempool.map.size, 1); | ||
}); | ||
Comment on lines
+213
to
+234
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This looks more like a mempool test than a miner test. Do we need to add it? Is this error already covered in the mempool tests? |
||
|
||
it('should include child transaction if child pays enough fee (CPFP)', async () => { | ||
const fee = 1000; | ||
|
||
// Fee should be enough for both the first transation and second transaction | ||
assert(fee > 140 + 108); | ||
Comment on lines
+239
to
+240
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Where did you get these values from (140 and 108)? It might be more clear to see the values pulled from the MempoolEntry itself is possible. In addition, asserting that the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh yea, I'll fix that, sorry mb there, I was supposed to replace that with calculation for fee for both transactions, that was just supposed to be a placeholder |
||
|
||
const mtx = new MTX(); | ||
const change = wallet.createChange().getAddress(); | ||
const coin = Coin.fromTX(parentTX, 1, -1); | ||
|
||
mtx.addCoin(coin); | ||
mtx.addOutput(change, coin.value - fee); | ||
wallet.sign(mtx); | ||
const tx = mtx.toTX(); | ||
await mempool.addTX(tx, -1); | ||
// Both transactions in mempool | ||
assert.strictEqual(mempool.map.size, 2); | ||
|
||
const block = await miner.mineBlock(chain.tip, addr); | ||
await chain.add(block); | ||
|
||
// Both transactions should get mined into the block | ||
assert.strictEqual(mempool.map.size, 0); | ||
assert.strictEqual(block.txs.length, 3); | ||
}); | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this test block should begin either with a
mempool.reset()
or assertion that mempool is empty. What might be even better is starting a newdescribe
block calledCPFP
or something. Especially since the "should not include free transaction in a block" test is basically a duplicate. We know we can't include free TXs in blocks from L127-L165.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yea I think a separate describe block is better, since this itself got way too long for just miner test. or maybe a complete different test file for CPFP and in future RBF (and other fee bumping mechanisms) might be better.