(self)
| 267 | ]) |
| 268 | |
| 269 | def test_rbf(self): |
| 270 | node = self.nodes[0] |
| 271 | coin = self.coins.pop() |
| 272 | inputs = [{"txid": coin["txid"], "vout": 0, "sequence": BIP125_SEQUENCE_NUMBER}] |
| 273 | fee = Decimal('0.00125000') |
| 274 | output = [{node.get_deterministic_priv_key().address: 50 - fee}, {"fee" : fee}] |
| 275 | raw_replaceable_tx = node.createrawtransaction(inputs, output) |
| 276 | signed_replaceable_tx = node.signrawtransactionwithkey(hexstring=raw_replaceable_tx, privkeys=self.privkeys) |
| 277 | testres_replaceable = node.testmempoolaccept([signed_replaceable_tx["hex"]]) |
| 278 | replaceable_tx = tx_from_hex(signed_replaceable_tx["hex"]) |
| 279 | assert_equal(testres_replaceable, [ |
| 280 | {"txid": replaceable_tx.rehash(), "wtxid": replaceable_tx.getwtxid(), |
| 281 | "allowed": True, "vsize": replaceable_tx.get_vsize(), "fees": { "base": fee }} |
| 282 | ]) |
| 283 | |
| 284 | # Replacement transaction is identical except has double the fee |
| 285 | replacement_tx = tx_from_hex(signed_replaceable_tx["hex"]) |
| 286 | replacement_tx.vout[0].nValue = CTxOutValue(int((50 - 2*fee) * COIN)) # Doubled fee |
| 287 | replacement_tx.vout[1].nValue = CTxOutValue(int(2*fee * COIN)) # Doubled fee |
| 288 | signed_replacement_tx = node.signrawtransactionwithkey(replacement_tx.serialize().hex(), self.privkeys) |
| 289 | replacement_tx = tx_from_hex(signed_replacement_tx["hex"]) |
| 290 | |
| 291 | self.log.info("Test that transactions within a package cannot replace each other") |
| 292 | testres_rbf_conflicting = node.testmempoolaccept([signed_replaceable_tx["hex"], signed_replacement_tx["hex"]]) |
| 293 | assert_equal(testres_rbf_conflicting, [ |
| 294 | {"txid": replaceable_tx.rehash(), "wtxid": replaceable_tx.getwtxid(), "package-error": "conflict-in-package"}, |
| 295 | {"txid": replacement_tx.rehash(), "wtxid": replacement_tx.getwtxid(), "package-error": "conflict-in-package"} |
| 296 | ]) |
| 297 | |
| 298 | self.log.info("Test that packages cannot conflict with mempool transactions, even if a valid BIP125 RBF") |
| 299 | node.sendrawtransaction(signed_replaceable_tx["hex"]) |
| 300 | testres_rbf_single = node.testmempoolaccept([signed_replacement_tx["hex"]]) |
| 301 | # This transaction is a valid BIP125 replace-by-fee |
| 302 | assert testres_rbf_single[0]["allowed"] |
| 303 | testres_rbf_package = self.independent_txns_testres_blank + [{ |
| 304 | "txid": replacement_tx.rehash(), "wtxid": replacement_tx.getwtxid(), "allowed": False, |
| 305 | "reject-reason": "bip125-replacement-disallowed" |
| 306 | }] |
| 307 | self.assert_testres_equal(self.independent_txns_hex + [signed_replacement_tx["hex"]], testres_rbf_package) |
| 308 | |
| 309 | if __name__ == "__main__": |
| 310 | RPCPackagesTest().main() |
no test coverage detected