|
| 1 | +#!/usr/bin/env python3 |
| 2 | +# Copyright (c) 2020 The DIVI developers |
| 3 | +# Distributed under the MIT/X11 software license, see the accompanying |
| 4 | +# file COPYING or http://www.opensource.org/licenses/mit-license.php. |
| 5 | + |
| 6 | +# Tests the policy changes in wallet and mempool around the |
| 7 | +# segwit-light activation time that prevent spending of |
| 8 | +# unconfirmed outputs. |
| 9 | + |
| 10 | +from test_framework import BitcoinTestFramework |
| 11 | +from util import * |
| 12 | + |
| 13 | +from PowToPosTransition import createPoSStacks, generatePoSBlocks |
| 14 | + |
| 15 | +ACTIVATION_TIME = 2_000_000_000 |
| 16 | + |
| 17 | + |
| 18 | +class SegwitLightTest (BitcoinTestFramework): |
| 19 | + |
| 20 | + def setup_network (self, split=False): |
| 21 | + args = ["-debug", "-spendzeroconfchange"] |
| 22 | + self.nodes = start_nodes (2, self.options.tmpdir, extra_args=[args]*2) |
| 23 | + connect_nodes (self.nodes[0], 1) |
| 24 | + self.is_network_split = False |
| 25 | + |
| 26 | + def run_test (self): |
| 27 | + # Activate the fork and PoS. We go beyond the fork to ensure |
| 28 | + # the mempool/wallet limitations are lifted already. |
| 29 | + set_node_times (self.nodes, ACTIVATION_TIME + 3_600 * 24 * 7) |
| 30 | + reconnect_all (self.nodes) |
| 31 | + self.nodes[0].setgenerate (True, 1) |
| 32 | + sync_blocks (self.nodes) |
| 33 | + createPoSStacks (self.nodes[:1], self.nodes) |
| 34 | + generatePoSBlocks (self.nodes, 0, 100) |
| 35 | + blk = self.nodes[1].getblockheader (self.nodes[1].getbestblockhash ()) |
| 36 | + assert_greater_than (blk["time"], ACTIVATION_TIME) |
| 37 | + |
| 38 | + # Send some normal transactions from the wallet (but in a chain). |
| 39 | + self.nodes[0].sendtoaddress (self.nodes[1].getnewaddress (), 1_000) |
| 40 | + generatePoSBlocks (self.nodes, 0, 1) |
| 41 | + assert_equal (self.nodes[1].getbalance (), 1_000) |
| 42 | + addr = self.nodes[0].getnewaddress () |
| 43 | + id1 = self.nodes[1].sendtoaddress (addr, 900) |
| 44 | + id2 = self.nodes[1].sendtoaddress (addr, 90) |
| 45 | + id3 = self.nodes[1].sendtoaddress (addr, 9) |
| 46 | + assert_equal (set (self.nodes[1].getrawmempool ()), set ([id1, id2, id3])) |
| 47 | + sync_mempools (self.nodes) |
| 48 | + generatePoSBlocks (self.nodes, 0, 1) |
| 49 | + assert_equal (self.nodes[1].getrawmempool (), []) |
| 50 | + assert_greater_than (1, self.nodes[1].getbalance ()) |
| 51 | + |
| 52 | + # Build a transaction on top of an unconfirmed one, that we will malleate. |
| 53 | + # The prepared transaction should still be valid. For malleating, we use |
| 54 | + # funds on a 1-of-2 multisig address, and then change which wallet |
| 55 | + # is signing. |
| 56 | + keys = [ |
| 57 | + n.validateaddress (n.getnewaddress ())["pubkey"] |
| 58 | + for n in self.nodes |
| 59 | + ] |
| 60 | + multisig = self.nodes[0].addmultisigaddress (1, keys) |
| 61 | + assert_equal (self.nodes[1].addmultisigaddress (1, keys), multisig) |
| 62 | + txid0 = self.nodes[0].sendtoaddress (multisig, 1_000) |
| 63 | + data0 = self.nodes[0].getrawtransaction (txid0, 1) |
| 64 | + btxid = data0["baretxid"] |
| 65 | + outputIndex = None |
| 66 | + for i in range (len (data0["vout"])): |
| 67 | + if data0["vout"][i]["scriptPubKey"]["addresses"] == [multisig]: |
| 68 | + assert outputIndex is None |
| 69 | + outputIndex = i |
| 70 | + assert outputIndex is not None |
| 71 | + generatePoSBlocks (self.nodes, 0, 1) |
| 72 | + out = self.nodes[0].gettxout (btxid, outputIndex) |
| 73 | + assert_equal (out["confirmations"], 1) |
| 74 | + assert_equal (out["value"], 1_000) |
| 75 | + assert_equal (out["scriptPubKey"]["addresses"], [multisig]) |
| 76 | + |
| 77 | + inputs = [{"txid": btxid, "vout": outputIndex}] |
| 78 | + tempAddr = self.nodes[0].getnewaddress ("temp") |
| 79 | + outputs = {tempAddr: 999} |
| 80 | + unsigned1 = self.nodes[0].createrawtransaction (inputs, outputs) |
| 81 | + signed1 = self.nodes[0].signrawtransaction (unsigned1) |
| 82 | + assert_equal (signed1["complete"], True) |
| 83 | + signed1 = signed1["hex"] |
| 84 | + data1 = self.nodes[0].decoderawtransaction (signed1) |
| 85 | + |
| 86 | + prevtx = [ |
| 87 | + { |
| 88 | + "txid": data1["baretxid"], |
| 89 | + "vout": 0, |
| 90 | + "scriptPubKey": self.nodes[0].validateaddress (tempAddr)["scriptPubKey"], |
| 91 | + } |
| 92 | + ] |
| 93 | + inputs = [{"txid": data1["baretxid"], "vout": 0}] |
| 94 | + finalAddr = self.nodes[1].getnewaddress ("final") |
| 95 | + outputs = {finalAddr: 998} |
| 96 | + unsigned2 = self.nodes[0].createrawtransaction (inputs, outputs) |
| 97 | + signed2 = self.nodes[0].signrawtransaction (unsigned2, prevtx) |
| 98 | + assert_equal (signed2["complete"], True) |
| 99 | + signed2 = signed2["hex"] |
| 100 | + data2 = self.nodes[0].decoderawtransaction (signed2) |
| 101 | + |
| 102 | + signed1p = self.nodes[1].signrawtransaction (unsigned1) |
| 103 | + assert_equal (signed1p["complete"], True) |
| 104 | + signed1p = signed1p["hex"] |
| 105 | + data1p = self.nodes[0].decoderawtransaction (signed1p) |
| 106 | + assert_equal (data1["baretxid"], data1p["baretxid"]) |
| 107 | + assert data1["txid"] != data1p["txid"] |
| 108 | + |
| 109 | + self.nodes[0].sendrawtransaction (signed1p) |
| 110 | + self.nodes[0].sendrawtransaction (signed2) |
| 111 | + generatePoSBlocks (self.nodes, 0, 1) |
| 112 | + sync_blocks (self.nodes) |
| 113 | + assert_equal (self.nodes[1].getbalance ("final"), 998) |
| 114 | + |
| 115 | +if __name__ == '__main__': |
| 116 | + SegwitLightTest ().main () |
0 commit comments