175 lines
6.0 KiB
Python
Executable File
175 lines
6.0 KiB
Python
Executable File
#!/usr/bin/env python2
|
|
# Copyright (c) 2016 The Zcash developers
|
|
# Distributed under the MIT software license, see the accompanying
|
|
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
|
|
|
|
|
from test_framework.test_framework import BitcoinTestFramework
|
|
from test_framework.util import assert_equal, start_node, \
|
|
start_nodes, connect_nodes_bi, bitcoind_processes
|
|
|
|
import time
|
|
from decimal import Decimal
|
|
|
|
class WalletNullifiersTest (BitcoinTestFramework):
|
|
|
|
def setup_nodes(self):
|
|
return start_nodes(4, self.options.tmpdir,
|
|
extra_args=[['-experimentalfeatures', '-developerencryptwallet']] * 4)
|
|
|
|
def run_test (self):
|
|
# add zaddr to node 0
|
|
myzaddr0 = self.nodes[0].z_getnewaddress()
|
|
|
|
# send node 0 taddr to zaddr to get out of coinbase
|
|
mytaddr = self.nodes[0].getnewaddress();
|
|
recipients = []
|
|
recipients.append({"address":myzaddr0, "amount":Decimal('10.0')-Decimal('0.0001')}) # utxo amount less fee
|
|
myopid = self.nodes[0].z_sendmany(mytaddr, recipients)
|
|
|
|
opids = []
|
|
opids.append(myopid)
|
|
|
|
timeout = 120
|
|
status = None
|
|
for x in xrange(1, timeout):
|
|
results = self.nodes[0].z_getoperationresult(opids)
|
|
if len(results)==0:
|
|
time.sleep(1)
|
|
else:
|
|
status = results[0]["status"]
|
|
assert_equal("success", status)
|
|
mytxid = results[0]["result"]["txid"]
|
|
break
|
|
|
|
self.sync_all()
|
|
self.nodes[0].generate(1)
|
|
self.sync_all()
|
|
|
|
# add zaddr to node 2
|
|
myzaddr = self.nodes[2].z_getnewaddress()
|
|
|
|
# import node 2 zaddr into node 1
|
|
myzkey = self.nodes[2].z_exportkey(myzaddr)
|
|
self.nodes[1].z_importkey(myzkey)
|
|
|
|
# encrypt node 1 wallet and wait to terminate
|
|
self.nodes[1].encryptwallet("test")
|
|
bitcoind_processes[1].wait()
|
|
|
|
# restart node 1
|
|
self.nodes[1] = start_node(1, self.options.tmpdir)
|
|
connect_nodes_bi(self.nodes, 0, 1)
|
|
connect_nodes_bi(self.nodes, 1, 2)
|
|
self.sync_all()
|
|
|
|
# send node 0 zaddr to note 2 zaddr
|
|
recipients = []
|
|
recipients.append({"address":myzaddr, "amount":7.0})
|
|
myopid = self.nodes[0].z_sendmany(myzaddr0, recipients)
|
|
|
|
opids = []
|
|
opids.append(myopid)
|
|
|
|
timeout = 120
|
|
status = None
|
|
for x in xrange(1, timeout):
|
|
results = self.nodes[0].z_getoperationresult(opids)
|
|
if len(results)==0:
|
|
time.sleep(1)
|
|
else:
|
|
status = results[0]["status"]
|
|
assert_equal("success", status)
|
|
mytxid = results[0]["result"]["txid"]
|
|
break
|
|
|
|
self.sync_all()
|
|
self.nodes[0].generate(1)
|
|
self.sync_all()
|
|
|
|
# check zaddr balance
|
|
zsendmanynotevalue = Decimal('7.0')
|
|
assert_equal(self.nodes[2].z_getbalance(myzaddr), zsendmanynotevalue)
|
|
assert_equal(self.nodes[1].z_getbalance(myzaddr), zsendmanynotevalue)
|
|
|
|
# add zaddr to node 3
|
|
myzaddr3 = self.nodes[3].z_getnewaddress()
|
|
|
|
# send node 2 zaddr to note 3 zaddr
|
|
recipients = []
|
|
recipients.append({"address":myzaddr3, "amount":2.0})
|
|
myopid = self.nodes[2].z_sendmany(myzaddr, recipients)
|
|
|
|
opids = []
|
|
opids.append(myopid)
|
|
|
|
timeout = 120
|
|
status = None
|
|
for x in xrange(1, timeout):
|
|
results = self.nodes[2].z_getoperationresult(opids)
|
|
if len(results)==0:
|
|
time.sleep(1)
|
|
else:
|
|
status = results[0]["status"]
|
|
assert_equal("success", status)
|
|
mytxid = results[0]["result"]["txid"]
|
|
break
|
|
|
|
self.sync_all()
|
|
self.nodes[2].generate(1)
|
|
self.sync_all()
|
|
|
|
# check zaddr balance
|
|
zsendmany2notevalue = Decimal('2.0')
|
|
zsendmanyfee = Decimal('0.0001')
|
|
zaddrremaining = zsendmanynotevalue - zsendmany2notevalue - zsendmanyfee
|
|
assert_equal(self.nodes[3].z_getbalance(myzaddr3), zsendmany2notevalue)
|
|
assert_equal(self.nodes[2].z_getbalance(myzaddr), zaddrremaining)
|
|
|
|
# Parallel encrypted wallet can't cache nullifiers for received notes,
|
|
# and therefore can't detect spends. So it sees a balance corresponding
|
|
# to the sum of both notes it received (one as change).
|
|
# TODO: Devise a way to avoid this issue (#1528)
|
|
assert_equal(self.nodes[1].z_getbalance(myzaddr), zsendmanynotevalue + zaddrremaining)
|
|
|
|
# send node 2 zaddr 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})
|
|
myopid = self.nodes[1].z_sendmany(myzaddr, recipients)
|
|
|
|
opids = []
|
|
opids.append(myopid)
|
|
|
|
timeout = 120
|
|
status = None
|
|
for x in xrange(1, timeout):
|
|
results = self.nodes[1].z_getoperationresult(opids)
|
|
if len(results)==0:
|
|
time.sleep(1)
|
|
else:
|
|
status = results[0]["status"]
|
|
assert_equal("success", status)
|
|
mytxid = results[0]["result"]["txid"]
|
|
[mytxid] # hush pyflakes
|
|
break
|
|
|
|
self.sync_all()
|
|
self.nodes[1].generate(1)
|
|
self.sync_all()
|
|
|
|
# check zaddr 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')
|
|
zaddrremaining2 = zaddrremaining - zsendmany3notevalue - zsendmanyfee
|
|
assert_equal(self.nodes[1].z_getbalance(myzaddr), zaddrremaining2)
|
|
assert_equal(self.nodes[2].z_getbalance(myzaddr), zaddrremaining2)
|
|
|
|
if __name__ == '__main__':
|
|
WalletNullifiersTest().main ()
|