def run_test(self):
        self.nodes[0].generate(110)

        # Obtain some transparent funds
        midAddr = self.nodes[0].getnewshieldaddress()
        # Shield almost all the balance
        self.nodes[0].shieldsendmany(get_coinstake_address(self.nodes[0]),
                                     [{
                                         "address": midAddr,
                                         "amount": Decimal(2400)
                                     }])

        self.sync_all()
        self.nodes[1].generate(1)
        self.sync_all()
        taddrSource = self.nodes[0].getnewaddress()
        for _ in range(6):
            recipients = [{"address": taddrSource, "amount": Decimal('3')}]
            self.nodes[0].shieldsendmany(midAddr, recipients, 1)
            self.sync_all()
            self.nodes[1].generate(1)
            self.sync_all()

        def check_change_taddr_reuse(target, isTargetShielded):
            recipients = [{"address": target, "amount": Decimal('1')}]

            # Send funds to recipient address twice
            txid1 = self.nodes[0].shieldsendmany(taddrSource, recipients, 1)
            self.nodes[1].generate(1)
            self.sync_all()
            txid2 = self.nodes[0].shieldsendmany(taddrSource, recipients, 1)
            self.nodes[1].generate(1)
            self.sync_all()

            # Verify that the two transactions used different change addresses
            tx1 = self.nodes[0].getrawtransaction(txid1, 1)
            tx2 = self.nodes[0].getrawtransaction(txid2, 1)
            assert_true(len(tx1['vout']) >= 1)  # at least one output
            assert_true(len(tx2['vout']) >= 1)
            for i in range(len(tx1['vout'])):
                tx1OutAddrs = tx1['vout'][i]['scriptPubKey']['addresses']
                tx2OutAddrs = tx2['vout'][i]['scriptPubKey']['addresses']
                if tx1OutAddrs != [target]:
                    print('Source address:     %s' % taddrSource)
                    print('TX1 change address: %s' % tx1OutAddrs[0])
                    print('TX2 change address: %s' % tx2OutAddrs[0])
                    assert (tx1OutAddrs != tx2OutAddrs)

        taddr = self.nodes[0].getnewaddress()
        saplingAddr = self.nodes[0].getnewshieldaddress()

        print()
        print('Checking shieldsendmany(taddr->Sapling)')
        check_change_taddr_reuse(saplingAddr, True)
        print()
        print('Checking shieldsendmany(taddr->taddr)')
        check_change_taddr_reuse(taddr, False)
Esempio n. 2
0
    def run_test(self):
        node = self.nodes[0]
        node.generate(110)

        # Obtain some transparent funds
        midAddr = node.getnewshieldaddress()
        # Shield almost all the balance
        node.shieldsendmany(get_coinstake_address(node),
                            [{
                                "address": midAddr,
                                "amount": Decimal(2400)
                            }])
        node.generate(1)
        taddrSource = node.getnewaddress()
        for _ in range(6):
            recipients = [{"address": taddrSource, "amount": Decimal('3')}]
            node.shieldsendmany(midAddr, recipients, 1)
            node.generate(1)

        def check_change_taddr_reuse(target):
            recipients = [{"address": target, "amount": Decimal('1')}]

            # Send funds to recipient address twice
            txid1 = node.shieldsendmany(taddrSource, recipients, 1)
            node.generate(1)
            txid2 = node.shieldsendmany(taddrSource, recipients, 1)
            node.generate(1)

            # Verify that the two transactions used different change addresses
            tx1 = node.getrawtransaction(txid1, 1)
            tx2 = node.getrawtransaction(txid2, 1)
            assert_greater_than_or_equal(len(tx1['vout']),
                                         1)  # at least one output
            assert_greater_than_or_equal(len(tx2['vout']), 1)
            for i in range(len(tx1['vout'])):
                tx1OutAddrs = tx1['vout'][i]['scriptPubKey']['addresses'][0]
                tx2OutAddrs = tx2['vout'][i]['scriptPubKey']['addresses'][0]
                if tx1OutAddrs != target:
                    self.log.info('Source address:     %s' % taddrSource)
                    self.log.info('TX1 change address: %s' % tx1OutAddrs)
                    self.log.info('TX2 change address: %s' % tx2OutAddrs)
                    assert tx1OutAddrs != tx2OutAddrs

        taddr = node.getnewaddress()
        saplingAddr = node.getnewshieldaddress()

        self.log.info('Checking shieldsendmany(taddr->Sapling)')
        check_change_taddr_reuse(saplingAddr)
        self.log.info('Checking shieldsendmany(taddr->taddr)')
        check_change_taddr_reuse(taddr)
Esempio n. 3
0
    def run_test(self):
        self.nodes[0].generate(2)
        self.sync_all()
        assert_equal(self.nodes[1].getblockcount(), 202)
        taddr1 = self.nodes[1].getnewaddress()
        saplingAddr0 = self.nodes[0].getnewshieldedaddress()
        saplingAddr1 = self.nodes[1].getnewshieldedaddress()

        # Verify addresses
        assert (saplingAddr0 in self.nodes[0].listshieldedaddresses())
        assert (saplingAddr1 in self.nodes[1].listshieldedaddresses())

        # Verify balance
        assert_equal(self.nodes[0].getshieldedbalance(saplingAddr0),
                     Decimal('0'))
        assert_equal(self.nodes[1].getshieldedbalance(saplingAddr1),
                     Decimal('0'))
        assert_equal(self.nodes[1].getreceivedbyaddress(taddr1), Decimal('0'))

        recipients = [{"address": saplingAddr0, "amount": Decimal('10')}]

        # Try fee too low
        fee_too_low = 0.001
        self.log.info("Trying to send a transaction with fee too low...")
        assert_raises_rpc_error(
            -4, "Fee set (%.3f) too low. Must be at least" % fee_too_low,
            self.nodes[0].rawshieldedsendmany, "from_transparent", recipients,
            1, fee_too_low)

        # Try fee too high.
        fee_too_high = 20
        self.log.info(
            "Good. It was not possible. Now try a tx with fee too high...")
        assert_raises_rpc_error(
            -4, "The transaction fee is too high: %.2f >" % fee_too_high,
            self.nodes[0].rawshieldedsendmany, "from_transparent", recipients,
            1, fee_too_high)

        # Trying to send a rawtx with low fee directly
        self.log.info("Good. It was not possible. Now try with a raw tx...")
        self.restart_node(0,
                          extra_args=self.extra_args[0] +
                          ['-minrelaytxfee=0.0000001'])
        rawtx = self.nodes[0].rawshieldedsendmany("from_transparent",
                                                  recipients, 1)["hex"]
        self.restart_node(0, extra_args=self.extra_args[0])
        connect_nodes(self.nodes[0], 1)
        assert_raises_rpc_error(-26, "insufficient fee",
                                self.nodes[0].sendrawtransaction, rawtx)
        self.log.info("Good. Not accepted in the mempool.")

        # Fixed fee
        fee = 1

        # Node 0 shields some funds
        # taddr -> Sapling
        self.log.info("TX 1: shield funds from specified transparent address.")
        mytxid1 = self.nodes[0].shieldedsendmany(
            get_coinstake_address(self.nodes[0]), recipients, 1, fee)

        # shield more funds automatically selecting the transparent inputs
        self.log.info("TX 2: shield funds from any transparent address.")
        mytxid2 = self.nodes[0].shieldedsendmany("from_transparent",
                                                 recipients, 1, fee)

        # Verify priority of tx is INF_PRIORITY, defined as 1E+25 (10000000000000000000000000)
        self.check_tx_priority([mytxid1, mytxid2])
        self.log.info("Priority for tx1 and tx2 checks out")

        self.nodes[2].generate(1)
        self.sync_all()

        # shield more funds creating and then sending a raw transaction
        self.log.info(
            "TX 3: shield funds creating and sending raw transaction.")
        tx_json = self.nodes[0].rawshieldedsendmany("from_transparent",
                                                    recipients, 1, fee)

        # Check SPORK_20 for sapling maintenance mode
        SPORK_20 = "SPORK_20_SAPLING_MAINTENANCE"
        self.activate_spork(0, SPORK_20)
        self.wait_for_spork(True, SPORK_20)
        assert_raises_rpc_error(-26, "bad-tx-sapling-maintenance",
                                self.nodes[0].sendrawtransaction,
                                tx_json["hex"])
        self.log.info("Good. Not accepted when SPORK_20 is active.")

        # Try with RPC...
        assert_raises_rpc_error(-8,
                                "Invalid parameter, Sapling not active yet",
                                self.nodes[0].shieldedsendmany,
                                "from_transparent", recipients, 1, fee)

        # Disable SPORK_20 and retry
        sleep(5)
        self.deactivate_spork(0, SPORK_20)
        self.wait_for_spork(False, SPORK_20)
        mytxid3 = self.nodes[0].sendrawtransaction(tx_json["hex"])
        self.log.info("Good. Accepted when SPORK_20 is not active.")

        # Verify priority of tx is INF_PRIORITY, defined as 1E+25 (10000000000000000000000000)
        self.check_tx_priority([mytxid3])
        self.log.info("Priority for tx3 checks out")

        self.nodes[2].generate(1)
        self.sync_all()

        # Verify balance
        assert_equal(self.nodes[0].getshieldedbalance(saplingAddr0),
                     Decimal('30'))
        assert_equal(self.nodes[1].getshieldedbalance(saplingAddr1),
                     Decimal('0'))
        assert_equal(self.nodes[1].getreceivedbyaddress(taddr1), Decimal('0'))
        self.log.info("Balances check out")

        # Now disconnect the block, activate SPORK_20, and try to reconnect it
        disconnect_nodes(self.nodes[0], 1)
        tip_hash = self.nodes[0].getbestblockhash()
        self.nodes[0].invalidateblock(tip_hash)
        assert tip_hash != self.nodes[0].getbestblockhash()
        assert_equal(self.nodes[0].getshieldedbalance(saplingAddr0),
                     Decimal('20'))
        self.log.info(
            "Now trying to connect block with shielded tx, when SPORK_20 is active"
        )
        self.activate_spork(0, SPORK_20)
        self.nodes[0].reconsiderblock(tip_hash)
        assert tip_hash != self.nodes[0].getbestblockhash(
        )  # Block NOT connected
        assert_equal(self.nodes[0].getshieldedbalance(saplingAddr0),
                     Decimal('20'))
        self.log.info("Good. Not possible.")

        # Deactivate SPORK_20 and reconnect
        sleep(1)
        self.deactivate_spork(0, SPORK_20)
        self.nodes[0].reconsiderblock(tip_hash)
        assert_equal(tip_hash,
                     self.nodes[0].getbestblockhash())  # Block connected
        assert_equal(self.nodes[0].getshieldedbalance(saplingAddr0),
                     Decimal('30'))
        self.log.info(
            "Reconnected after deactivation of SPORK_20. Balance restored.")
        connect_nodes(self.nodes[0], 1)

        # Node 0 sends some shielded funds to node 1
        # Sapling -> Sapling
        #         -> Sapling (change)
        self.log.info(
            "TX 4: shielded transaction from specified sapling address.")
        recipients4 = [{"address": saplingAddr1, "amount": Decimal('10')}]
        mytxid4 = self.nodes[0].shieldedsendmany(saplingAddr0, recipients4, 1,
                                                 fee)
        self.check_tx_priority([mytxid4])

        self.nodes[2].generate(1)
        self.sync_all()

        # Send more shielded funds (this time with automatic selection of the source)
        self.log.info("TX 5: shielded transaction from any sapling address.")
        recipients5 = [{"address": saplingAddr1, "amount": Decimal('5')}]
        mytxid5 = self.nodes[0].shieldedsendmany("from_shielded", recipients5,
                                                 1, fee)
        self.check_tx_priority([mytxid5])

        self.nodes[2].generate(1)
        self.sync_all()

        # Send more shielded funds (with create + send raw transaction)
        self.log.info("TX 6: shielded raw transaction.")
        tx_json = self.nodes[0].rawshieldedsendmany("from_shielded",
                                                    recipients5, 1, fee)
        mytxid6 = self.nodes[0].sendrawtransaction(tx_json["hex"])
        self.check_tx_priority([mytxid6])

        self.nodes[2].generate(1)
        self.sync_all()

        # Shield more funds to a different address to verify multi-source notes spending
        saplingAddr2 = self.nodes[0].getnewshieldedaddress()
        self.log.info(
            "TX 7: shield funds to later verify multi source notes spending.")
        recipients = [{"address": saplingAddr2, "amount": Decimal('10')}]
        mytxid7 = self.nodes[0].shieldedsendmany(
            get_coinstake_address(self.nodes[0]), recipients, 1, fee)
        self.check_tx_priority([mytxid7])

        self.nodes[2].generate(5)
        self.sync_all()

        # Verify multi-source notes spending
        tAddr0 = self.nodes[0].getnewaddress()
        self.log.info("TX 8: verifying multi source notes spending.")
        recipients = [{"address": tAddr0, "amount": Decimal('11')}]
        mytxid8 = self.nodes[0].shieldedsendmany("from_shielded", recipients,
                                                 1, fee)
        self.check_tx_priority([mytxid8])

        self.nodes[2].generate(1)
        self.sync_all()

        # Verify balance
        assert_equal(self.nodes[0].getshieldedbalance(saplingAddr0),
                     Decimal('3'))  # 30 received - (20 sent + 3 fee) - 4 sent
        assert_equal(self.nodes[1].getshieldedbalance(saplingAddr1),
                     Decimal('20'))  # 20 received
        assert_equal(self.nodes[0].getshieldedbalance(saplingAddr2),
                     Decimal('2'))  # 10 received - 10 sent + 2 change
        assert_equal(self.nodes[1].getreceivedbyaddress(taddr1), Decimal('0'))
        assert_equal(self.nodes[0].getshieldedbalance(), Decimal('5'))
        self.log.info("Balances check out")

        # Node 1 sends some shielded funds to node 0, as well as unshielding
        # Sapling -> Sapling
        #         -> taddr
        #         -> Sapling (change)
        self.log.info("TX 10: deshield funds from specified sapling address.")
        recipients7 = [{"address": saplingAddr0, "amount": Decimal('8')}]
        recipients7.append({"address": taddr1, "amount": Decimal('10')})
        mytxid7 = self.nodes[1].shieldedsendmany(saplingAddr1, recipients7, 1,
                                                 fee)
        self.check_tx_priority([mytxid7])

        self.nodes[2].generate(1)
        self.sync_all()

        # Verify balance
        assert_equal(self.nodes[0].getshieldedbalance(saplingAddr0),
                     Decimal('11'))  # 3 prev balance + 8 received
        assert_equal(self.nodes[1].getshieldedbalance(saplingAddr1),
                     Decimal('1'))  # 20 prev balance - (18 sent + 1 fee)
        assert_equal(self.nodes[1].getreceivedbyaddress(taddr1), Decimal('10'))
        self.log.info("Balances check out")

        # Verify existence of Sapling related JSON fields
        resp = self.nodes[0].getrawtransaction(mytxid7, 1)
        assert_equal(Decimal(resp['valueBalance']), Decimal(
            '11.00'))  # 20 shielded input - 8 shielded spend - 1 change
        assert_equal(len(resp['vShieldedSpend']), 3)
        assert_equal(len(resp['vShieldedOutput']), 2)
        assert ('bindingSig' in resp)
        shieldedSpend = resp['vShieldedSpend'][0]
        assert ('cv' in shieldedSpend)
        assert ('anchor' in shieldedSpend)
        assert ('nullifier' in shieldedSpend)
        assert ('rk' in shieldedSpend)
        assert ('proof' in shieldedSpend)
        assert ('spendAuthSig' in shieldedSpend)
        shieldedOutput = resp['vShieldedOutput'][0]
        assert ('cv' in shieldedOutput)
        assert ('cmu' in shieldedOutput)
        assert ('ephemeralKey' in shieldedOutput)
        assert ('encCiphertext' in shieldedOutput)
        assert ('outCiphertext' in shieldedOutput)
        assert ('proof' in shieldedOutput)
        self.log.info("Raw transaction decoding checks out")

        # Verify importing a spending key will update the nullifiers and witnesses correctly
        self.log.info("Checking exporting/importing a spending key...")
        sk0 = self.nodes[0].exportsaplingkey(saplingAddr0)
        saplingAddrInfo0 = self.nodes[2].importsaplingkey(sk0, "yes")
        assert_equal(saplingAddrInfo0["address"], saplingAddr0)
        assert_equal(
            self.nodes[2].getshieldedbalance(saplingAddrInfo0["address"]),
            Decimal('11'))
        sk1 = self.nodes[1].exportsaplingkey(saplingAddr1)
        saplingAddrInfo1 = self.nodes[2].importsaplingkey(sk1, "yes")
        assert_equal(saplingAddrInfo1["address"], saplingAddr1)
        assert_equal(
            self.nodes[2].getshieldedbalance(saplingAddrInfo1["address"]),
            Decimal('1'))

        # Verify importing a viewing key will update the nullifiers and witnesses correctly
        self.log.info("Checking exporting/importing a viewing key...")
        extfvk0 = self.nodes[0].exportsaplingviewingkey(saplingAddr0)
        saplingAddrInfo0 = self.nodes[3].importsaplingviewingkey(
            extfvk0, "yes")
        assert_equal(saplingAddrInfo0["address"], saplingAddr0)
        assert_equal(
            Decimal(self.nodes[3].getshieldedbalance(
                saplingAddrInfo0["address"], 1, True)), Decimal('11'))
        extfvk1 = self.nodes[1].exportsaplingviewingkey(saplingAddr1)
        saplingAddrInfo1 = self.nodes[3].importsaplingviewingkey(
            extfvk1, "yes")
        assert_equal(saplingAddrInfo1["address"], saplingAddr1)
        assert_equal(
            self.nodes[3].getshieldedbalance(saplingAddrInfo1["address"], 1,
                                             True), Decimal('1'))
        # no balance in the wallet
        assert_equal(self.nodes[3].getshieldedbalance(), Decimal('0'))
        # watch only balance
        assert_equal(self.nodes[3].getshieldedbalance("*", 1, True),
                     Decimal('12.00'))

        # Now shield some funds using sendmany
        self.log.info(
            "TX11: Shielding coins to multiple destinations with sendmany RPC..."
        )
        prev_balance = self.nodes[0].getbalance()
        recipients8 = {
            saplingAddr0: Decimal('8'),
            saplingAddr1: Decimal('1'),
            saplingAddr2: Decimal('0.5')
        }
        mytxid11 = self.nodes[0].sendmany("", recipients8)
        self.check_tx_priority([mytxid11])
        self.log.info("Done. Checking details and balances...")

        # Decrypted transaction details should be correct
        pt = self.nodes[0].viewshieldedtransaction(mytxid11)
        fee = pt["fee"]
        assert_equal(pt['txid'], mytxid11)
        assert_equal(len(pt['spends']), 0)
        assert_equal(len(pt['outputs']), 3)
        found = [False] * 3
        for out in pt['outputs']:
            assert_equal(pt['outputs'].index(out), out['output'])
            if out['address'] == saplingAddr0:
                assert_equal(out['outgoing'], False)
                assert_equal(out['value'], Decimal('8'))
                found[0] = True
            elif out['address'] == saplingAddr1:
                assert_equal(out['outgoing'], True)
                assert_equal(out['value'], Decimal('1'))
                found[1] = True
            else:
                assert_equal(out['address'], saplingAddr2)
                assert_equal(out['outgoing'], False)
                assert_equal(out['value'], Decimal('0.5'))
                found[2] = True
        assert_equal(found, [True] * 3)

        # Verify balance
        self.nodes[2].generate(1)
        self.sync_all()
        assert_equal(self.nodes[0].getshieldedbalance(saplingAddr0),
                     Decimal('19'))  # 11 prev balance + 8 received
        assert_equal(self.nodes[1].getshieldedbalance(saplingAddr1),
                     Decimal('2'))  # 1 prev balance + 1 received
        assert_equal(self.nodes[0].getshieldedbalance(saplingAddr2),
                     Decimal('2.5'))  # 2 prev balance + 0.5 received
        # Balance of node 0 is: prev_balance - 1 PIV (+fee) sent externally +  250 PIV matured coinbase
        assert_equal(
            self.nodes[0].getbalance(),
            satoshi_round(prev_balance + Decimal('249') - Decimal(fee)))

        # Now shield some funds using sendtoaddress
        self.log.info("TX12: Shielding coins with sendtoaddress RPC...")
        prev_balance = self.nodes[0].getbalance()
        mytxid12 = self.nodes[0].sendtoaddress(saplingAddr0, Decimal('10'))
        self.check_tx_priority([mytxid12])
        self.log.info("Done. Checking details and balances...")

        # Decrypted transaction details should be correct
        pt = self.nodes[0].viewshieldedtransaction(mytxid12)
        fee = pt["fee"]
        assert_equal(pt['txid'], mytxid12)
        assert_equal(len(pt['spends']), 0)
        assert_equal(len(pt['outputs']), 1)
        out = pt['outputs'][0]
        assert_equal(out['address'], saplingAddr0)
        assert_equal(out['outgoing'], False)
        assert_equal(out['value'], Decimal('10'))

        # Verify balance
        self.nodes[2].generate(1)
        self.sync_all()
        assert_equal(self.nodes[0].getshieldedbalance(saplingAddr0),
                     Decimal('29'))  # 19 prev balance + 10 received

        self.log.info("All good.")
Esempio n. 4
0
    def run_test (self):
        self.nodes[0].generate(1) # activate Sapling
        self.sync_all()

        # add shield addr to node 0
        myzaddr0 = self.nodes[0].getnewshieldaddress()

        # send node 0 taddr to shield addr to get out of coinbase
        # Tests using the default cached chain have one address per coinbase output
        mytaddr = get_coinstake_address(self.nodes[0])
        recipients = []
        recipients.append({"address":myzaddr0, "amount":Decimal('10.0') - Decimal('1')}) # utxo amount less fee

        self.nodes[0].shieldsendmany(mytaddr, recipients)
        self.nodes[0].generate(1)
        self.sync_all()

        # add shield addr to node 2
        myzaddr = self.nodes[2].getnewshieldaddress()

        # import node 2 shield addr into node 1
        myzkey = self.nodes[2].exportsaplingkey(myzaddr)
        self.nodes[1].importsaplingkey(myzkey)

        # encrypt node 1 wallet and wait to terminate
        self.nodes[1].encryptwallet("test")

        # send node 0  shield addr to note 2 zaddr
        recipients = []
        recipients.append({"address":myzaddr, "amount":7.0})

        txid = self.nodes[0].shieldsendmany(myzaddr0, recipients)

        self.sync_all()
        self.nodes[0].generate(1)
        self.sync_all()

        # check shield addr balance
        zsendmanynotevalue = Decimal('7.0')
        assert_equal(self.nodes[2].getshieldbalance(myzaddr), zsendmanynotevalue)
        assert_equal(self.nodes[1].getshieldbalance(myzaddr), zsendmanynotevalue)

        # add shield addr to node 3
        myzaddr3 = self.nodes[3].getnewshieldaddress()

        # send node 2 shield addr to note 3 shield addr
        recipients = []
        recipients.append({"address":myzaddr3, "amount":2.0})

        txid = self.nodes[2].shieldsendmany(myzaddr, recipients)

        self.sync_all()
        self.nodes[2].generate(1)
        self.sync_all()

        # check shield addr balance
        zsendmany2notevalue = Decimal('2.0')
        zsendmanyfee = Decimal(self.nodes[2].viewshieldtransaction(txid)['fee'])
        zaddrremaining = zsendmanynotevalue - zsendmany2notevalue - zsendmanyfee
        assert_equal(self.nodes[3].getshieldbalance(myzaddr3), zsendmany2notevalue)
        assert_equal(self.nodes[2].getshieldbalance(myzaddr), zaddrremaining)
        assert_equal(self.nodes[1].getshieldbalance(myzaddr), zaddrremaining)

        # send node 2 shield addr on node 1 to taddr
        # This requires that node 1 be unlocked, which triggers caching of
        # uncached nullifiers.
        self.nodes[1].walletpassphrase("test", 600)
        mytaddr1 = self.nodes[1].getnewaddress()
        recipients = []
        recipients.append({"address":mytaddr1, "amount":1.0})

        txid = self.nodes[1].shieldsendmany(myzaddr, recipients)

        self.sync_all()
        self.nodes[1].generate(1)
        self.sync_all()

        # check shield addr balance
        # Now that the encrypted wallet has been unlocked, the note nullifiers
        # have been cached and spent notes can be detected. Thus the two wallets
        # are in agreement once more.
        zsendmany3notevalue = Decimal('1.0')
        zsendmanyfee = Decimal(self.nodes[1].viewshieldtransaction(txid)['fee'])
        zaddrremaining2 = zaddrremaining - zsendmany3notevalue - zsendmanyfee
        assert_equal(self.nodes[1].getshieldbalance(myzaddr), zaddrremaining2)
        assert_equal(self.nodes[2].getshieldbalance(myzaddr), zaddrremaining2)

        # Test viewing keys

        node3mined = Decimal('6250.0')
        assert_equal(self.nodes[3].getshieldbalance(), zsendmany2notevalue)
        assert_equal(self.nodes[3].getbalance(1, False, True, False), node3mined)

        # Add node 1 address and node 2 viewing key to node 3
        myzvkey = self.nodes[2].exportsaplingviewingkey(myzaddr)
        self.nodes[3].importaddress(mytaddr1)
        importvk_result = self.nodes[3].importsaplingviewingkey(myzvkey, 'whenkeyisnew', 1)

        # Check results of importsaplingviewingkey
        assert_equal(importvk_result["address"], myzaddr)

        # Check the address has been imported
        assert_equal(myzaddr in self.nodes[3].listshieldaddresses(), False)
        assert_equal(myzaddr in self.nodes[3].listshieldaddresses(True), True)

        # Node 3 should see the same received notes as node 2; however, there are 2 things:
        # - Some of the notes were change for node 2 but not for node 3.
        # - Each node wallet store transaction time as received. As
        #   `wait_and_assert_operationid_status` is called node 2 and 3 are off by a few seconds.
        # Aside from that the received notes should be the same. So,
        # group by txid and then check that all properties aside from
        # change are equal.
        node2Received = dict([r['txid'], r] for r in self.nodes[2].listreceivedbyshieldaddress(myzaddr))
        node3Received = dict([r['txid'], r] for r in self.nodes[3].listreceivedbyshieldaddress(myzaddr))
        assert_equal(len(node2Received), len(node2Received))
        for txid in node2Received:
            received2 = node2Received[txid]
            received3 = node3Received[txid]
            # the change field will be omitted for received3, but all other fields should be shared
            assert_true(len(received2) >= len(received3))
            for key in received2:
                # check all the properties except for change and blocktime
                if key != 'change' and key != 'blocktime':
                    assert_equal(received2[key], received3[key])

        # Node 3's balances should be unchanged without explicitly requesting
        # to include watch-only balances
        assert_equal(self.nodes[3].getshieldbalance(), zsendmany2notevalue)
        assert_equal(self.nodes[3].getbalance(1, False, True, False), node3mined)

        assert_equal(self.nodes[3].getshieldbalance("*", 1, True), zsendmany2notevalue + zaddrremaining2)
        assert_equal(self.nodes[3].getbalance(1, True, True, False), node3mined + Decimal('1.0'))

        # Check individual balances reflect the above
        assert_equal(self.nodes[3].getreceivedbyaddress(mytaddr1), Decimal('1.0'))
        assert_equal(self.nodes[3].getshieldbalance(myzaddr), Decimal('0.0'))
        assert_equal(self.nodes[3].getshieldbalance(myzaddr, 1, True), zaddrremaining2)
Esempio n. 5
0
    def run_test(self):
        # generate 100 more to activate sapling in regtest
        self.nodes[2].generate(12)
        self.sync_all()
        self.nodes[0].generate(360)
        # Sanity-check the test harness
        assert_equal(self.nodes[0].getblockcount(), 372)

        taddr1 = self.nodes[1].getnewaddress()
        saplingAddr0 = self.nodes[0].getnewshieldedaddress()
        saplingAddr1 = self.nodes[1].getnewshieldedaddress()

        # Verify addresses
        assert(saplingAddr0 in self.nodes[0].listshieldedaddresses())
        assert(saplingAddr1 in self.nodes[1].listshieldedaddresses())
        assert_equal(self.nodes[0].validateaddress(saplingAddr0)['type'], 'sapling')
        assert_equal(self.nodes[0].validateaddress(saplingAddr1)['type'], 'sapling')

        # Verify balance
        assert_equal(self.nodes[0].getshieldedbalance(saplingAddr0), Decimal('0'))
        assert_equal(self.nodes[1].getshieldedbalance(saplingAddr1), Decimal('0'))
        assert_equal(self.nodes[1].getreceivedbyaddress(taddr1), Decimal('0'))

        # Hardcoded min sapling fee
        nMinDefaultSaplingFee = 1

        # Node 0 shields some funds
        # taddr -> Sapling
        recipients = []
        recipients.append({"address": saplingAddr0, "amount": Decimal('10')})
        coinstake = get_coinstake_address(self.nodes[0])
        mytxid = self.nodes[0].shielded_sendmany(coinstake, recipients, 1, nMinDefaultSaplingFee)

        self.sync_all()

        # Verify priority of tx is INF_PRIORITY, defined as 1E+25 (10000000000000000000000000)
        mempool = self.nodes[0].getrawmempool(True)
        self.check_tx_priority(mempool, mytxid)

        # Shield another coinbase UTXO
        mytxid = self.nodes[0].shielded_sendmany(get_coinstake_address(self.nodes[0]), recipients, 1, nMinDefaultSaplingFee)

        self.sync_all()
        self.nodes[2].generate(1)
        self.sync_all()

        # Verify balance
        assert_equal(self.nodes[0].getshieldedbalance(saplingAddr0), Decimal('20'))
        assert_equal(self.nodes[1].getshieldedbalance(saplingAddr1), Decimal('0'))
        assert_equal(self.nodes[1].getreceivedbyaddress(taddr1), Decimal('0'))

        # Node 0 sends some shielded funds to node 1
        # Sapling -> Sapling
        #         -> Sapling (change)
        recipients = []
        recipients.append({"address": saplingAddr1, "amount": Decimal('15')})
        mytxid = self.nodes[0].shielded_sendmany(saplingAddr0, recipients, 1, nMinDefaultSaplingFee)

        self.sync_all()

        # Verify priority of tx is MAX_PRIORITY, defined as 1E+25 (10000000000000000000000000)
        mempool = self.nodes[0].getrawmempool(True)
        self.check_tx_priority(mempool, mytxid)

        self.nodes[2].generate(1)
        self.sync_all()

        # Verify balance
        assert_equal(self.nodes[0].getshieldedbalance(saplingAddr0), Decimal('4')) # 20 receive - (15 sent + 1 fee)
        assert_equal(self.nodes[1].getshieldedbalance(saplingAddr1), Decimal('15'))
        assert_equal(self.nodes[1].getreceivedbyaddress(taddr1), Decimal('0'))

        # Node 1 sends some shielded funds to node 0, as well as unshielding
        # Sapling -> Sapling
        #         -> taddr
        #         -> Sapling (change)
        recipients = []
        recipients.append({"address": saplingAddr0, "amount": Decimal('5')})
        recipients.append({"address": taddr1, "amount": Decimal('5')})
        mytxid = self.nodes[1].shielded_sendmany(saplingAddr1, recipients, 1, nMinDefaultSaplingFee)
        self.sync_all()

        # Verify priority of tx is MAX_PRIORITY, defined as 1E+25 (10000000000000000000000000)
        mempool = self.nodes[1].getrawmempool(True)
        self.check_tx_priority(mempool, mytxid)

        self.nodes[2].generate(1)
        self.sync_all()

        # Verify balance
        assert_equal(self.nodes[0].getshieldedbalance(saplingAddr0), Decimal('9')) # 20 receive - (15 sent + 1 fee) + 5 receive
        assert_equal(self.nodes[1].getshieldedbalance(saplingAddr1), Decimal('4'))
        assert_equal(self.nodes[1].getreceivedbyaddress(taddr1), Decimal('5'))

        # Verify existence of Sapling related JSON fields
        resp = self.nodes[0].getrawtransaction(mytxid, 1)
        assert_equal(Decimal(resp['valueBalance']), Decimal('6.00')) # 15 shielded input - 5 shielded spend - 4 change
        assert(len(resp['vShieldedSpend']) == 1)
        assert(len(resp['vShieldedOutput']) == 2)
        assert('bindingSig' in resp)
        shieldedSpend = resp['vShieldedSpend'][0]
        assert('cv' in shieldedSpend)
        assert('anchor' in shieldedSpend)
        assert('nullifier' in shieldedSpend)
        assert('rk' in shieldedSpend)
        assert('proof' in shieldedSpend)
        assert('spendAuthSig' in shieldedSpend)
        shieldedOutput = resp['vShieldedOutput'][0]
        assert('cv' in shieldedOutput)
        assert('cmu' in shieldedOutput)
        assert('ephemeralKey' in shieldedOutput)
        assert('encCiphertext' in shieldedOutput)
        assert('outCiphertext' in shieldedOutput)
        assert('proof' in shieldedOutput)

        # Verify importing a spending key will update the nullifiers and witnesses correctly
        sk0 = self.nodes[0].exportsaplingkey(saplingAddr0)
        saplingAddrInfo0 = self.nodes[2].importsaplingkey(sk0, "yes")
        assert_equal(saplingAddrInfo0["address"], saplingAddr0)
        assert_equal(self.nodes[2].getshieldedbalance(saplingAddrInfo0["address"]), Decimal('9'))
        sk1 = self.nodes[1].exportsaplingkey(saplingAddr1)
        saplingAddrInfo1 = self.nodes[2].importsaplingkey(sk1, "yes")
        assert_equal(saplingAddrInfo1["address"], saplingAddr1)
        assert_equal(self.nodes[2].getshieldedbalance(saplingAddrInfo1["address"]), Decimal('4'))

        # Verify importing a viewing key will update the nullifiers and witnesses correctly
        extfvk0 = self.nodes[0].exportsaplingviewingkey(saplingAddr0)
        saplingAddrInfo0 = self.nodes[3].importsaplingviewingkey(extfvk0, "yes")
        assert_equal(saplingAddrInfo0["address"], saplingAddr0)
        assert_equal(Decimal(self.nodes[3].getshieldedbalance(saplingAddrInfo0["address"], 1, True)), Decimal('9'))
        extfvk1 = self.nodes[1].exportsaplingviewingkey(saplingAddr1)
        saplingAddrInfo1 = self.nodes[3].importsaplingviewingkey(extfvk1, "yes")
        assert_equal(saplingAddrInfo1["address"], saplingAddr1)
        assert_equal(self.nodes[3].getshieldedbalance(saplingAddrInfo1["address"], 1, True), Decimal('4'))

        # Verify that getshieldedbalance only includes watch-only addresses when requested
        shieldedBalance = self.nodes[3].getshieldedbalance()
        # no balance in the wallet
        assert_equal(shieldedBalance, Decimal('0'))

        shieldedBalance = self.nodes[3].getshieldedbalance("*", 1, True)
        # watch only balance
        assert_equal(shieldedBalance, Decimal('13.00'))
    def run_test(self):
        self.nodes[0].generate(
            4)  # generate blocks to activate sapling in regtest
        # verify sapling activation.
        assert (self.nodes[0].getblockchaininfo()['upgrades']['v5 shield']
                ['activationheight'] == 1)

        self.sync_all()

        walletinfo = self.nodes[0].getwalletinfo()
        assert_equal(self.nodes[0].getblockcount(),
                     walletinfo['last_processed_block'])
        assert_equal(walletinfo['immature_balance'], 1000)
        assert_equal(walletinfo['balance'], 0)

        self.sync_all()
        self.nodes[1].generate(102)
        self.sync_all()

        assert_equal(self.nodes[0].getbalance(), 1000)
        assert_equal(self.nodes[1].getbalance(), 500)
        assert_equal(self.nodes[2].getbalance(), 0)

        # At this point in time, commitment tree is the empty root

        # Node 0 creates a shield transaction
        mytaddr0 = get_coinstake_address(self.nodes[0])
        myzaddr0 = self.nodes[0].getnewshieldaddress()
        recipients = []
        recipients.append({
            "address": myzaddr0,
            "amount": Decimal('10.0') - Decimal('0.0001')
        })
        txid = self.nodes[0].shieldsendmany(mytaddr0, recipients)

        # Sync up mempools and mine the transaction.  All nodes have the same anchor.
        self.sync_all()
        self.nodes[0].generate(1)
        self.sync_all()

        # Stop nodes.
        self.stop_nodes()

        # Relaunch nodes and partition network into two:
        # A: node 0
        # B: node 1, 2

        self.start_node(0, self.extra_args[0])
        self.start_node(1, self.extra_args[1])
        self.start_node(2, self.extra_args[2])
        connect_nodes(self.nodes[1], 2)

        # Partition B, node 1 mines an empty block
        self.nodes[1].generate(1)
        self.sync_blocks(self.nodes[1:3])

        # Check partition
        assert_equal(self.nodes[1].getblockcount(),
                     self.nodes[2].getblockcount())
        assert (self.nodes[2].getblockcount() != self.nodes[0].getblockcount())

        # Partition A, node 0 creates a shield transaction
        recipients = []
        recipients.append({
            "address": myzaddr0,
            "amount": Decimal('10.0') - Decimal('0.0001')
        })
        txid = self.nodes[0].shieldsendmany(mytaddr0, recipients)
        rawhex = self.nodes[0].getrawtransaction(txid)

        # Partition A, node 0 mines a block with the transaction
        self.nodes[0].generate(1)
        self.sync_all(self.nodes[1:3])

        # Partition B, node 1 mines the same shield transaction
        txid2 = self.nodes[1].sendrawtransaction(rawhex)
        assert_equal(txid, txid2)
        self.nodes[1].generate(1)

        # Check that Partition B is one block ahead and that they have different tips
        assert_equal(self.nodes[0].getblockcount() + 1,
                     self.nodes[1].getblockcount())
        assert (self.nodes[0].getbestblockhash() !=
                self.nodes[1].getbestblockhash())

        # Shut down all nodes so any in-memory state is saved to disk
        self.stop_nodes()

        # Relaunch nodes and reconnect the entire network
        self.start_nodes()
        connect_nodes(self.nodes[0], 1)
        connect_nodes(self.nodes[2], 1)
        connect_nodes(self.nodes[2], 0)

        # Mine a new block and let it propagate
        self.nodes[1].generate(1)
        self.sync_all()

        assert_equal(self.nodes[0].getbestblockhash(),
                     self.nodes[1].getbestblockhash())
        assert_equal(self.nodes[1].getbestblockhash(),
                     self.nodes[2].getbestblockhash())
Esempio n. 7
0
    def run_test(self):
        self.log.info("Mining 120 blocks...")
        self.nodes[0].generate(120)
        self.sync_all()
        # Sanity-check the test harness
        assert_equal([x.getblockcount() for x in self.nodes],
                     [120] * self.num_nodes)

        taddr1 = self.nodes[1].getnewaddress()
        saplingAddr0 = self.nodes[0].getnewshieldedaddress()
        saplingAddr1 = self.nodes[1].getnewshieldedaddress()

        # Verify addresses
        assert (saplingAddr0 in self.nodes[0].listshieldedaddresses())
        assert (saplingAddr1 in self.nodes[1].listshieldedaddresses())
        assert_equal(self.nodes[0].validateaddress(saplingAddr0)['type'],
                     'sapling')
        assert_equal(self.nodes[0].validateaddress(saplingAddr1)['type'],
                     'sapling')

        # Verify balance
        assert_equal(self.nodes[0].getshieldedbalance(saplingAddr0),
                     Decimal('0'))
        assert_equal(self.nodes[1].getshieldedbalance(saplingAddr1),
                     Decimal('0'))
        assert_equal(self.nodes[1].getreceivedbyaddress(taddr1), Decimal('0'))

        # Fixed fee
        fee = 1

        # Node 0 shields some funds
        # taddr -> Sapling
        self.log.info("TX 1: shield funds from specified transparent address.")
        recipients = [{"address": saplingAddr0, "amount": Decimal('10')}]
        mytxid1 = self.nodes[0].shieldedsendmany(
            get_coinstake_address(self.nodes[0]), recipients, 1, fee)

        # shield more funds automatically selecting the transparent inputs
        self.log.info("TX 2: shield funds from any transparent address.")
        mytxid2 = self.nodes[0].shieldedsendmany("from_transparent",
                                                 recipients, 1, fee)

        # shield more funds creating and then sending a raw transaction
        self.log.info(
            "TX 3: shield funds creating and sending raw transaction.")
        tx_json = self.nodes[0].rawshieldedsendmany("from_transparent",
                                                    recipients, 1, fee)
        mytxid3 = self.nodes[0].sendrawtransaction(tx_json["hex"])

        # Verify priority of tx is INF_PRIORITY, defined as 1E+25 (10000000000000000000000000)
        self.check_tx_priority([mytxid1, mytxid2, mytxid3])
        self.log.info("Priority for tx1, tx2 and tx3 checks out")

        self.nodes[2].generate(1)
        self.sync_all()

        # Verify balance
        assert_equal(self.nodes[0].getshieldedbalance(saplingAddr0),
                     Decimal('30'))
        assert_equal(self.nodes[1].getshieldedbalance(saplingAddr1),
                     Decimal('0'))
        assert_equal(self.nodes[1].getreceivedbyaddress(taddr1), Decimal('0'))
        self.log.info("Balances check out")

        # Node 0 sends some shielded funds to node 1
        # Sapling -> Sapling
        #         -> Sapling (change)
        self.log.info(
            "TX 4: shielded transaction from specified sapling address.")
        recipients4 = [{"address": saplingAddr1, "amount": Decimal('10')}]
        mytxid4 = self.nodes[0].shieldedsendmany(saplingAddr0, recipients4, 1,
                                                 fee)
        self.check_tx_priority([mytxid4])

        self.nodes[2].generate(1)
        self.sync_all()

        # Send more shielded funds (this time with automatic selection of the source)
        self.log.info("TX 5: shielded transaction from any sapling address.")
        recipients5 = [{"address": saplingAddr1, "amount": Decimal('5')}]
        mytxid5 = self.nodes[0].shieldedsendmany("from_shielded", recipients5,
                                                 1, fee)
        self.check_tx_priority([mytxid5])

        self.nodes[2].generate(1)
        self.sync_all()

        # Send more shielded funds (with create + send raw transaction)
        self.log.info("TX 6: shielded raw transaction.")
        tx_json = self.nodes[0].rawshieldedsendmany("from_shielded",
                                                    recipients5, 1, fee)
        mytxid6 = self.nodes[0].sendrawtransaction(tx_json["hex"])
        self.check_tx_priority([mytxid6])

        self.nodes[2].generate(1)
        self.sync_all()

        # Verify balance
        assert_equal(self.nodes[0].getshieldedbalance(saplingAddr0),
                     Decimal('7'))  # 30 received - (20 sent + 3 fee)
        assert_equal(self.nodes[1].getshieldedbalance(saplingAddr1),
                     Decimal('20'))  # 20 received
        assert_equal(self.nodes[1].getreceivedbyaddress(taddr1), Decimal('0'))
        self.log.info("Balances check out")

        # Node 1 sends some shielded funds to node 0, as well as unshielding
        # Sapling -> Sapling
        #         -> taddr
        #         -> Sapling (change)
        self.log.info("TX 7: deshield funds from specified sapling address.")
        recipients7 = [{"address": saplingAddr0, "amount": Decimal('8')}]
        recipients7.append({"address": taddr1, "amount": Decimal('10')})
        mytxid7 = self.nodes[1].shieldedsendmany(saplingAddr1, recipients7, 1,
                                                 fee)
        self.check_tx_priority([mytxid7])

        self.nodes[2].generate(1)
        self.sync_all()

        # Verify balance
        assert_equal(self.nodes[0].getshieldedbalance(saplingAddr0),
                     Decimal('15'))  # 7 prev balance + 8 received
        assert_equal(self.nodes[1].getshieldedbalance(saplingAddr1),
                     Decimal('1'))  # 20 prev balance - (18 sent + 1 fee)
        assert_equal(self.nodes[1].getreceivedbyaddress(taddr1), Decimal('10'))
        self.log.info("Balances check out")

        # Verify existence of Sapling related JSON fields
        resp = self.nodes[0].getrawtransaction(mytxid7, 1)
        assert_equal(Decimal(resp['valueBalance']), Decimal(
            '11.00'))  # 20 shielded input - 8 shielded spend - 1 change
        assert_equal(len(resp['vShieldedSpend']), 3)
        assert_equal(len(resp['vShieldedOutput']), 2)
        assert ('bindingSig' in resp)
        shieldedSpend = resp['vShieldedSpend'][0]
        assert ('cv' in shieldedSpend)
        assert ('anchor' in shieldedSpend)
        assert ('nullifier' in shieldedSpend)
        assert ('rk' in shieldedSpend)
        assert ('proof' in shieldedSpend)
        assert ('spendAuthSig' in shieldedSpend)
        shieldedOutput = resp['vShieldedOutput'][0]
        assert ('cv' in shieldedOutput)
        assert ('cmu' in shieldedOutput)
        assert ('ephemeralKey' in shieldedOutput)
        assert ('encCiphertext' in shieldedOutput)
        assert ('outCiphertext' in shieldedOutput)
        assert ('proof' in shieldedOutput)
        self.log.info("Raw transaction decoding checks out")

        # Verify importing a spending key will update the nullifiers and witnesses correctly
        self.log.info("Checking exporting/importing a spending key...")
        sk0 = self.nodes[0].exportsaplingkey(saplingAddr0)
        saplingAddrInfo0 = self.nodes[2].importsaplingkey(sk0, "yes")
        assert_equal(saplingAddrInfo0["address"], saplingAddr0)
        assert_equal(
            self.nodes[2].getshieldedbalance(saplingAddrInfo0["address"]),
            Decimal('15'))
        sk1 = self.nodes[1].exportsaplingkey(saplingAddr1)
        saplingAddrInfo1 = self.nodes[2].importsaplingkey(sk1, "yes")
        assert_equal(saplingAddrInfo1["address"], saplingAddr1)
        assert_equal(
            self.nodes[2].getshieldedbalance(saplingAddrInfo1["address"]),
            Decimal('1'))

        # Verify importing a viewing key will update the nullifiers and witnesses correctly
        self.log.info("Checking exporting/importing a viewing key...")
        extfvk0 = self.nodes[0].exportsaplingviewingkey(saplingAddr0)
        saplingAddrInfo0 = self.nodes[3].importsaplingviewingkey(
            extfvk0, "yes")
        assert_equal(saplingAddrInfo0["address"], saplingAddr0)
        assert_equal(
            Decimal(self.nodes[3].getshieldedbalance(
                saplingAddrInfo0["address"], 1, True)), Decimal('15'))
        extfvk1 = self.nodes[1].exportsaplingviewingkey(saplingAddr1)
        saplingAddrInfo1 = self.nodes[3].importsaplingviewingkey(
            extfvk1, "yes")
        assert_equal(saplingAddrInfo1["address"], saplingAddr1)
        assert_equal(
            self.nodes[3].getshieldedbalance(saplingAddrInfo1["address"], 1,
                                             True), Decimal('1'))
        # no balance in the wallet
        assert_equal(self.nodes[3].getshieldedbalance(), Decimal('0'))
        # watch only balance
        assert_equal(self.nodes[3].getshieldedbalance("*", 1, True),
                     Decimal('16.00'))

        self.log.info("All good.")