Merge #7822: Add listunspent() test for spendable/unspendable UTXO
5d217de
Add test to check spendable and unspendable UTXO on RPC listunspent (Joao Fonseca)fa942c7
Move method to check matches within arrays on util.py (Joao Fonseca)
This commit is contained in:
commit
0e6fd5e4af
7 changed files with 98 additions and 145 deletions
|
@ -6,28 +6,6 @@
|
||||||
from test_framework.test_framework import BitcoinTestFramework
|
from test_framework.test_framework import BitcoinTestFramework
|
||||||
from test_framework.util import *
|
from test_framework.util import *
|
||||||
|
|
||||||
|
|
||||||
def check_array_result(object_array, to_match, expected):
|
|
||||||
"""
|
|
||||||
Pass in array of JSON objects, a dictionary with key/value pairs
|
|
||||||
to match against, and another dictionary with expected key/value
|
|
||||||
pairs.
|
|
||||||
"""
|
|
||||||
num_matched = 0
|
|
||||||
for item in object_array:
|
|
||||||
all_match = True
|
|
||||||
for key,value in to_match.items():
|
|
||||||
if item[key] != value:
|
|
||||||
all_match = False
|
|
||||||
if not all_match:
|
|
||||||
continue
|
|
||||||
for key,value in expected.items():
|
|
||||||
if item[key] != value:
|
|
||||||
raise AssertionError("%s : expected %s=%s"%(str(item), str(key), str(value)))
|
|
||||||
num_matched = num_matched+1
|
|
||||||
if num_matched == 0:
|
|
||||||
raise AssertionError("No objects matched %s"%(str(to_match)))
|
|
||||||
|
|
||||||
import threading
|
import threading
|
||||||
|
|
||||||
class LongpollThread(threading.Thread):
|
class LongpollThread(threading.Thread):
|
||||||
|
|
|
@ -10,28 +10,6 @@ from binascii import a2b_hex, b2a_hex
|
||||||
from hashlib import sha256
|
from hashlib import sha256
|
||||||
from struct import pack
|
from struct import pack
|
||||||
|
|
||||||
|
|
||||||
def check_array_result(object_array, to_match, expected):
|
|
||||||
"""
|
|
||||||
Pass in array of JSON objects, a dictionary with key/value pairs
|
|
||||||
to match against, and another dictionary with expected key/value
|
|
||||||
pairs.
|
|
||||||
"""
|
|
||||||
num_matched = 0
|
|
||||||
for item in object_array:
|
|
||||||
all_match = True
|
|
||||||
for key,value in to_match.items():
|
|
||||||
if item[key] != value:
|
|
||||||
all_match = False
|
|
||||||
if not all_match:
|
|
||||||
continue
|
|
||||||
for key,value in expected.items():
|
|
||||||
if item[key] != value:
|
|
||||||
raise AssertionError("%s : expected %s=%s"%(str(item), str(key), str(value)))
|
|
||||||
num_matched = num_matched+1
|
|
||||||
if num_matched == 0:
|
|
||||||
raise AssertionError("No objects matched %s"%(str(to_match)))
|
|
||||||
|
|
||||||
def b2x(b):
|
def b2x(b):
|
||||||
return b2a_hex(b).decode('ascii')
|
return b2a_hex(b).decode('ascii')
|
||||||
|
|
||||||
|
|
|
@ -10,28 +10,6 @@
|
||||||
from test_framework.test_framework import BitcoinTestFramework
|
from test_framework.test_framework import BitcoinTestFramework
|
||||||
from test_framework.util import *
|
from test_framework.util import *
|
||||||
|
|
||||||
|
|
||||||
def check_array_result(object_array, to_match, expected):
|
|
||||||
"""
|
|
||||||
Pass in array of JSON objects, a dictionary with key/value pairs
|
|
||||||
to match against, and another dictionary with expected key/value
|
|
||||||
pairs.
|
|
||||||
"""
|
|
||||||
num_matched = 0
|
|
||||||
for item in object_array:
|
|
||||||
all_match = True
|
|
||||||
for key,value in to_match.items():
|
|
||||||
if item[key] != value:
|
|
||||||
all_match = False
|
|
||||||
if not all_match:
|
|
||||||
continue
|
|
||||||
for key,value in expected.items():
|
|
||||||
if item[key] != value:
|
|
||||||
raise AssertionError("%s : expected %s=%s"%(str(item), str(key), str(value)))
|
|
||||||
num_matched = num_matched+1
|
|
||||||
if num_matched == 0:
|
|
||||||
raise AssertionError("No objects matched %s"%(str(to_match)))
|
|
||||||
|
|
||||||
class KeyPoolTest(BitcoinTestFramework):
|
class KeyPoolTest(BitcoinTestFramework):
|
||||||
|
|
||||||
def run_test(self):
|
def run_test(self):
|
||||||
|
|
|
@ -16,27 +16,6 @@ def txFromHex(hexstring):
|
||||||
tx.deserialize(f)
|
tx.deserialize(f)
|
||||||
return tx
|
return tx
|
||||||
|
|
||||||
def check_array_result(object_array, to_match, expected):
|
|
||||||
"""
|
|
||||||
Pass in array of JSON objects, a dictionary with key/value pairs
|
|
||||||
to match against, and another dictionary with expected key/value
|
|
||||||
pairs.
|
|
||||||
"""
|
|
||||||
num_matched = 0
|
|
||||||
for item in object_array:
|
|
||||||
all_match = True
|
|
||||||
for key,value in to_match.items():
|
|
||||||
if item[key] != value:
|
|
||||||
all_match = False
|
|
||||||
if not all_match:
|
|
||||||
continue
|
|
||||||
for key,value in expected.items():
|
|
||||||
if item[key] != value:
|
|
||||||
raise AssertionError("%s : expected %s=%s"%(str(item), str(key), str(value)))
|
|
||||||
num_matched = num_matched+1
|
|
||||||
if num_matched == 0:
|
|
||||||
raise AssertionError("No objects matched %s"%(str(to_match)))
|
|
||||||
|
|
||||||
class ListTransactionsTest(BitcoinTestFramework):
|
class ListTransactionsTest(BitcoinTestFramework):
|
||||||
|
|
||||||
def setup_nodes(self):
|
def setup_nodes(self):
|
||||||
|
@ -48,28 +27,28 @@ class ListTransactionsTest(BitcoinTestFramework):
|
||||||
# Simple send, 0 to 1:
|
# Simple send, 0 to 1:
|
||||||
txid = self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 0.1)
|
txid = self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 0.1)
|
||||||
self.sync_all()
|
self.sync_all()
|
||||||
check_array_result(self.nodes[0].listtransactions(),
|
assert_array_result(self.nodes[0].listtransactions(),
|
||||||
{"txid":txid},
|
{"txid":txid},
|
||||||
{"category":"send","account":"","amount":Decimal("-0.1"),"confirmations":0})
|
{"category":"send","account":"","amount":Decimal("-0.1"),"confirmations":0})
|
||||||
check_array_result(self.nodes[1].listtransactions(),
|
assert_array_result(self.nodes[1].listtransactions(),
|
||||||
{"txid":txid},
|
{"txid":txid},
|
||||||
{"category":"receive","account":"","amount":Decimal("0.1"),"confirmations":0})
|
{"category":"receive","account":"","amount":Decimal("0.1"),"confirmations":0})
|
||||||
# mine a block, confirmations should change:
|
# mine a block, confirmations should change:
|
||||||
self.nodes[0].generate(1)
|
self.nodes[0].generate(1)
|
||||||
self.sync_all()
|
self.sync_all()
|
||||||
check_array_result(self.nodes[0].listtransactions(),
|
assert_array_result(self.nodes[0].listtransactions(),
|
||||||
{"txid":txid},
|
{"txid":txid},
|
||||||
{"category":"send","account":"","amount":Decimal("-0.1"),"confirmations":1})
|
{"category":"send","account":"","amount":Decimal("-0.1"),"confirmations":1})
|
||||||
check_array_result(self.nodes[1].listtransactions(),
|
assert_array_result(self.nodes[1].listtransactions(),
|
||||||
{"txid":txid},
|
{"txid":txid},
|
||||||
{"category":"receive","account":"","amount":Decimal("0.1"),"confirmations":1})
|
{"category":"receive","account":"","amount":Decimal("0.1"),"confirmations":1})
|
||||||
|
|
||||||
# send-to-self:
|
# send-to-self:
|
||||||
txid = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 0.2)
|
txid = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 0.2)
|
||||||
check_array_result(self.nodes[0].listtransactions(),
|
assert_array_result(self.nodes[0].listtransactions(),
|
||||||
{"txid":txid, "category":"send"},
|
{"txid":txid, "category":"send"},
|
||||||
{"amount":Decimal("-0.2")})
|
{"amount":Decimal("-0.2")})
|
||||||
check_array_result(self.nodes[0].listtransactions(),
|
assert_array_result(self.nodes[0].listtransactions(),
|
||||||
{"txid":txid, "category":"receive"},
|
{"txid":txid, "category":"receive"},
|
||||||
{"amount":Decimal("0.2")})
|
{"amount":Decimal("0.2")})
|
||||||
|
|
||||||
|
@ -80,28 +59,28 @@ class ListTransactionsTest(BitcoinTestFramework):
|
||||||
self.nodes[1].getaccountaddress("toself") : 0.44 }
|
self.nodes[1].getaccountaddress("toself") : 0.44 }
|
||||||
txid = self.nodes[1].sendmany("", send_to)
|
txid = self.nodes[1].sendmany("", send_to)
|
||||||
self.sync_all()
|
self.sync_all()
|
||||||
check_array_result(self.nodes[1].listtransactions(),
|
assert_array_result(self.nodes[1].listtransactions(),
|
||||||
{"category":"send","amount":Decimal("-0.11")},
|
{"category":"send","amount":Decimal("-0.11")},
|
||||||
{"txid":txid} )
|
{"txid":txid} )
|
||||||
check_array_result(self.nodes[0].listtransactions(),
|
assert_array_result(self.nodes[0].listtransactions(),
|
||||||
{"category":"receive","amount":Decimal("0.11")},
|
{"category":"receive","amount":Decimal("0.11")},
|
||||||
{"txid":txid} )
|
{"txid":txid} )
|
||||||
check_array_result(self.nodes[1].listtransactions(),
|
assert_array_result(self.nodes[1].listtransactions(),
|
||||||
{"category":"send","amount":Decimal("-0.22")},
|
{"category":"send","amount":Decimal("-0.22")},
|
||||||
{"txid":txid} )
|
{"txid":txid} )
|
||||||
check_array_result(self.nodes[1].listtransactions(),
|
assert_array_result(self.nodes[1].listtransactions(),
|
||||||
{"category":"receive","amount":Decimal("0.22")},
|
{"category":"receive","amount":Decimal("0.22")},
|
||||||
{"txid":txid} )
|
{"txid":txid} )
|
||||||
check_array_result(self.nodes[1].listtransactions(),
|
assert_array_result(self.nodes[1].listtransactions(),
|
||||||
{"category":"send","amount":Decimal("-0.33")},
|
{"category":"send","amount":Decimal("-0.33")},
|
||||||
{"txid":txid} )
|
{"txid":txid} )
|
||||||
check_array_result(self.nodes[0].listtransactions(),
|
assert_array_result(self.nodes[0].listtransactions(),
|
||||||
{"category":"receive","amount":Decimal("0.33")},
|
{"category":"receive","amount":Decimal("0.33")},
|
||||||
{"txid":txid, "account" : "from1"} )
|
{"txid":txid, "account" : "from1"} )
|
||||||
check_array_result(self.nodes[1].listtransactions(),
|
assert_array_result(self.nodes[1].listtransactions(),
|
||||||
{"category":"send","amount":Decimal("-0.44")},
|
{"category":"send","amount":Decimal("-0.44")},
|
||||||
{"txid":txid, "account" : ""} )
|
{"txid":txid, "account" : ""} )
|
||||||
check_array_result(self.nodes[1].listtransactions(),
|
assert_array_result(self.nodes[1].listtransactions(),
|
||||||
{"category":"receive","amount":Decimal("0.44")},
|
{"category":"receive","amount":Decimal("0.44")},
|
||||||
{"txid":txid, "account" : "toself"} )
|
{"txid":txid, "account" : "toself"} )
|
||||||
|
|
||||||
|
@ -111,7 +90,7 @@ class ListTransactionsTest(BitcoinTestFramework):
|
||||||
self.nodes[1].generate(1)
|
self.nodes[1].generate(1)
|
||||||
self.sync_all()
|
self.sync_all()
|
||||||
assert(len(self.nodes[0].listtransactions("watchonly", 100, 0, False)) == 0)
|
assert(len(self.nodes[0].listtransactions("watchonly", 100, 0, False)) == 0)
|
||||||
check_array_result(self.nodes[0].listtransactions("watchonly", 100, 0, True),
|
assert_array_result(self.nodes[0].listtransactions("watchonly", 100, 0, True),
|
||||||
{"category":"receive","amount":Decimal("0.1")},
|
{"category":"receive","amount":Decimal("0.1")},
|
||||||
{"txid":txid, "account" : "watchonly"} )
|
{"txid":txid, "account" : "watchonly"} )
|
||||||
|
|
||||||
|
@ -139,9 +118,9 @@ class ListTransactionsTest(BitcoinTestFramework):
|
||||||
# 1. Chain a few transactions that don't opt-in.
|
# 1. Chain a few transactions that don't opt-in.
|
||||||
txid_1 = self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 1)
|
txid_1 = self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 1)
|
||||||
assert(not is_opt_in(self.nodes[0], txid_1))
|
assert(not is_opt_in(self.nodes[0], txid_1))
|
||||||
check_array_result(self.nodes[0].listtransactions(), {"txid": txid_1}, {"bip125-replaceable":"no"})
|
assert_array_result(self.nodes[0].listtransactions(), {"txid": txid_1}, {"bip125-replaceable":"no"})
|
||||||
sync_mempools(self.nodes)
|
sync_mempools(self.nodes)
|
||||||
check_array_result(self.nodes[1].listtransactions(), {"txid": txid_1}, {"bip125-replaceable":"no"})
|
assert_array_result(self.nodes[1].listtransactions(), {"txid": txid_1}, {"bip125-replaceable":"no"})
|
||||||
|
|
||||||
# Tx2 will build off txid_1, still not opting in to RBF.
|
# Tx2 will build off txid_1, still not opting in to RBF.
|
||||||
utxo_to_use = get_unconfirmed_utxo_entry(self.nodes[1], txid_1)
|
utxo_to_use = get_unconfirmed_utxo_entry(self.nodes[1], txid_1)
|
||||||
|
@ -155,9 +134,9 @@ class ListTransactionsTest(BitcoinTestFramework):
|
||||||
|
|
||||||
# ...and check the result
|
# ...and check the result
|
||||||
assert(not is_opt_in(self.nodes[1], txid_2))
|
assert(not is_opt_in(self.nodes[1], txid_2))
|
||||||
check_array_result(self.nodes[1].listtransactions(), {"txid": txid_2}, {"bip125-replaceable":"no"})
|
assert_array_result(self.nodes[1].listtransactions(), {"txid": txid_2}, {"bip125-replaceable":"no"})
|
||||||
sync_mempools(self.nodes)
|
sync_mempools(self.nodes)
|
||||||
check_array_result(self.nodes[0].listtransactions(), {"txid": txid_2}, {"bip125-replaceable":"no"})
|
assert_array_result(self.nodes[0].listtransactions(), {"txid": txid_2}, {"bip125-replaceable":"no"})
|
||||||
|
|
||||||
# Tx3 will opt-in to RBF
|
# Tx3 will opt-in to RBF
|
||||||
utxo_to_use = get_unconfirmed_utxo_entry(self.nodes[0], txid_2)
|
utxo_to_use = get_unconfirmed_utxo_entry(self.nodes[0], txid_2)
|
||||||
|
@ -171,9 +150,9 @@ class ListTransactionsTest(BitcoinTestFramework):
|
||||||
txid_3 = self.nodes[0].sendrawtransaction(tx3_signed)
|
txid_3 = self.nodes[0].sendrawtransaction(tx3_signed)
|
||||||
|
|
||||||
assert(is_opt_in(self.nodes[0], txid_3))
|
assert(is_opt_in(self.nodes[0], txid_3))
|
||||||
check_array_result(self.nodes[0].listtransactions(), {"txid": txid_3}, {"bip125-replaceable":"yes"})
|
assert_array_result(self.nodes[0].listtransactions(), {"txid": txid_3}, {"bip125-replaceable":"yes"})
|
||||||
sync_mempools(self.nodes)
|
sync_mempools(self.nodes)
|
||||||
check_array_result(self.nodes[1].listtransactions(), {"txid": txid_3}, {"bip125-replaceable":"yes"})
|
assert_array_result(self.nodes[1].listtransactions(), {"txid": txid_3}, {"bip125-replaceable":"yes"})
|
||||||
|
|
||||||
# Tx4 will chain off tx3. Doesn't signal itself, but depends on one
|
# Tx4 will chain off tx3. Doesn't signal itself, but depends on one
|
||||||
# that does.
|
# that does.
|
||||||
|
@ -185,9 +164,9 @@ class ListTransactionsTest(BitcoinTestFramework):
|
||||||
txid_4 = self.nodes[1].sendrawtransaction(tx4_signed)
|
txid_4 = self.nodes[1].sendrawtransaction(tx4_signed)
|
||||||
|
|
||||||
assert(not is_opt_in(self.nodes[1], txid_4))
|
assert(not is_opt_in(self.nodes[1], txid_4))
|
||||||
check_array_result(self.nodes[1].listtransactions(), {"txid": txid_4}, {"bip125-replaceable":"yes"})
|
assert_array_result(self.nodes[1].listtransactions(), {"txid": txid_4}, {"bip125-replaceable":"yes"})
|
||||||
sync_mempools(self.nodes)
|
sync_mempools(self.nodes)
|
||||||
check_array_result(self.nodes[0].listtransactions(), {"txid": txid_4}, {"bip125-replaceable":"yes"})
|
assert_array_result(self.nodes[0].listtransactions(), {"txid": txid_4}, {"bip125-replaceable":"yes"})
|
||||||
|
|
||||||
# Replace tx3, and check that tx4 becomes unknown
|
# Replace tx3, and check that tx4 becomes unknown
|
||||||
tx3_b = tx3_modified
|
tx3_b = tx3_modified
|
||||||
|
@ -197,9 +176,9 @@ class ListTransactionsTest(BitcoinTestFramework):
|
||||||
txid_3b = self.nodes[0].sendrawtransaction(tx3_b_signed, True)
|
txid_3b = self.nodes[0].sendrawtransaction(tx3_b_signed, True)
|
||||||
assert(is_opt_in(self.nodes[0], txid_3b))
|
assert(is_opt_in(self.nodes[0], txid_3b))
|
||||||
|
|
||||||
check_array_result(self.nodes[0].listtransactions(), {"txid": txid_4}, {"bip125-replaceable":"unknown"})
|
assert_array_result(self.nodes[0].listtransactions(), {"txid": txid_4}, {"bip125-replaceable":"unknown"})
|
||||||
sync_mempools(self.nodes)
|
sync_mempools(self.nodes)
|
||||||
check_array_result(self.nodes[1].listtransactions(), {"txid": txid_4}, {"bip125-replaceable":"unknown"})
|
assert_array_result(self.nodes[1].listtransactions(), {"txid": txid_4}, {"bip125-replaceable":"unknown"})
|
||||||
|
|
||||||
# Check gettransaction as well:
|
# Check gettransaction as well:
|
||||||
for n in self.nodes[0:2]:
|
for n in self.nodes[0:2]:
|
||||||
|
|
|
@ -25,32 +25,6 @@ def get_sub_array_from_array(object_array, to_match):
|
||||||
return item
|
return item
|
||||||
return []
|
return []
|
||||||
|
|
||||||
def check_array_result(object_array, to_match, expected, should_not_find = False):
|
|
||||||
"""
|
|
||||||
Pass in array of JSON objects, a dictionary with key/value pairs
|
|
||||||
to match against, and another dictionary with expected key/value
|
|
||||||
pairs.
|
|
||||||
If the should_not_find flag is true, to_match should not be found in object_array
|
|
||||||
"""
|
|
||||||
if should_not_find == True:
|
|
||||||
expected = { }
|
|
||||||
num_matched = 0
|
|
||||||
for item in object_array:
|
|
||||||
all_match = True
|
|
||||||
for key,value in to_match.items():
|
|
||||||
if item[key] != value:
|
|
||||||
all_match = False
|
|
||||||
if not all_match:
|
|
||||||
continue
|
|
||||||
for key,value in expected.items():
|
|
||||||
if item[key] != value:
|
|
||||||
raise AssertionError("%s : expected %s=%s"%(str(item), str(key), str(value)))
|
|
||||||
num_matched = num_matched+1
|
|
||||||
if num_matched == 0 and should_not_find != True:
|
|
||||||
raise AssertionError("No objects matched %s"%(str(to_match)))
|
|
||||||
if num_matched > 0 and should_not_find == True:
|
|
||||||
raise AssertionError("Objects was matched %s"%(str(to_match)))
|
|
||||||
|
|
||||||
class ReceivedByTest(BitcoinTestFramework):
|
class ReceivedByTest(BitcoinTestFramework):
|
||||||
|
|
||||||
def setup_nodes(self):
|
def setup_nodes(self):
|
||||||
|
@ -68,26 +42,26 @@ class ReceivedByTest(BitcoinTestFramework):
|
||||||
self.sync_all()
|
self.sync_all()
|
||||||
|
|
||||||
#Check not listed in listreceivedbyaddress because has 0 confirmations
|
#Check not listed in listreceivedbyaddress because has 0 confirmations
|
||||||
check_array_result(self.nodes[1].listreceivedbyaddress(),
|
assert_array_result(self.nodes[1].listreceivedbyaddress(),
|
||||||
{"address":addr},
|
{"address":addr},
|
||||||
{ },
|
{ },
|
||||||
True)
|
True)
|
||||||
#Bury Tx under 10 block so it will be returned by listreceivedbyaddress
|
#Bury Tx under 10 block so it will be returned by listreceivedbyaddress
|
||||||
self.nodes[1].generate(10)
|
self.nodes[1].generate(10)
|
||||||
self.sync_all()
|
self.sync_all()
|
||||||
check_array_result(self.nodes[1].listreceivedbyaddress(),
|
assert_array_result(self.nodes[1].listreceivedbyaddress(),
|
||||||
{"address":addr},
|
{"address":addr},
|
||||||
{"address":addr, "account":"", "amount":Decimal("0.1"), "confirmations":10, "txids":[txid,]})
|
{"address":addr, "account":"", "amount":Decimal("0.1"), "confirmations":10, "txids":[txid,]})
|
||||||
#With min confidence < 10
|
#With min confidence < 10
|
||||||
check_array_result(self.nodes[1].listreceivedbyaddress(5),
|
assert_array_result(self.nodes[1].listreceivedbyaddress(5),
|
||||||
{"address":addr},
|
{"address":addr},
|
||||||
{"address":addr, "account":"", "amount":Decimal("0.1"), "confirmations":10, "txids":[txid,]})
|
{"address":addr, "account":"", "amount":Decimal("0.1"), "confirmations":10, "txids":[txid,]})
|
||||||
#With min confidence > 10, should not find Tx
|
#With min confidence > 10, should not find Tx
|
||||||
check_array_result(self.nodes[1].listreceivedbyaddress(11),{"address":addr},{ },True)
|
assert_array_result(self.nodes[1].listreceivedbyaddress(11),{"address":addr},{ },True)
|
||||||
|
|
||||||
#Empty Tx
|
#Empty Tx
|
||||||
addr = self.nodes[1].getnewaddress()
|
addr = self.nodes[1].getnewaddress()
|
||||||
check_array_result(self.nodes[1].listreceivedbyaddress(0,True),
|
assert_array_result(self.nodes[1].listreceivedbyaddress(0,True),
|
||||||
{"address":addr},
|
{"address":addr},
|
||||||
{"address":addr, "account":"", "amount":0, "confirmations":0, "txids":[]})
|
{"address":addr, "account":"", "amount":0, "confirmations":0, "txids":[]})
|
||||||
|
|
||||||
|
@ -131,7 +105,7 @@ class ReceivedByTest(BitcoinTestFramework):
|
||||||
self.sync_all()
|
self.sync_all()
|
||||||
|
|
||||||
# listreceivedbyaccount should return received_by_account_json because of 0 confirmations
|
# listreceivedbyaccount should return received_by_account_json because of 0 confirmations
|
||||||
check_array_result(self.nodes[1].listreceivedbyaccount(),
|
assert_array_result(self.nodes[1].listreceivedbyaccount(),
|
||||||
{"account":account},
|
{"account":account},
|
||||||
received_by_account_json)
|
received_by_account_json)
|
||||||
|
|
||||||
|
@ -143,7 +117,7 @@ class ReceivedByTest(BitcoinTestFramework):
|
||||||
self.nodes[1].generate(10)
|
self.nodes[1].generate(10)
|
||||||
self.sync_all()
|
self.sync_all()
|
||||||
# listreceivedbyaccount should return updated account balance
|
# listreceivedbyaccount should return updated account balance
|
||||||
check_array_result(self.nodes[1].listreceivedbyaccount(),
|
assert_array_result(self.nodes[1].listreceivedbyaccount(),
|
||||||
{"account":account},
|
{"account":account},
|
||||||
{"account":received_by_account_json["account"], "amount":(received_by_account_json["amount"] + Decimal("0.1"))})
|
{"account":received_by_account_json["account"], "amount":(received_by_account_json["amount"] + Decimal("0.1"))})
|
||||||
|
|
||||||
|
|
|
@ -478,6 +478,35 @@ def assert_is_hash_string(string, length=64):
|
||||||
raise AssertionError(
|
raise AssertionError(
|
||||||
"String %r contains invalid characters for a hash." % string)
|
"String %r contains invalid characters for a hash." % string)
|
||||||
|
|
||||||
|
def assert_array_result(object_array, to_match, expected, should_not_find = False):
|
||||||
|
"""
|
||||||
|
Pass in array of JSON objects, a dictionary with key/value pairs
|
||||||
|
to match against, and another dictionary with expected key/value
|
||||||
|
pairs.
|
||||||
|
If the should_not_find flag is true, to_match should not be found
|
||||||
|
in object_array
|
||||||
|
"""
|
||||||
|
if should_not_find == True:
|
||||||
|
expected = { }
|
||||||
|
num_matched = 0
|
||||||
|
for item in object_array:
|
||||||
|
all_match = True
|
||||||
|
for key,value in to_match.items():
|
||||||
|
if item[key] != value:
|
||||||
|
all_match = False
|
||||||
|
if not all_match:
|
||||||
|
continue
|
||||||
|
elif should_not_find == True:
|
||||||
|
num_matched = num_matched+1
|
||||||
|
for key,value in expected.items():
|
||||||
|
if item[key] != value:
|
||||||
|
raise AssertionError("%s : expected %s=%s"%(str(item), str(key), str(value)))
|
||||||
|
num_matched = num_matched+1
|
||||||
|
if num_matched == 0 and should_not_find != True:
|
||||||
|
raise AssertionError("No objects matched %s"%(str(to_match)))
|
||||||
|
if num_matched > 0 and should_not_find == True:
|
||||||
|
raise AssertionError("Objects were found %s"%(str(to_match)))
|
||||||
|
|
||||||
def satoshi_round(amount):
|
def satoshi_round(amount):
|
||||||
return Decimal(amount).quantize(Decimal('0.00000001'), rounding=ROUND_DOWN)
|
return Decimal(amount).quantize(Decimal('0.00000001'), rounding=ROUND_DOWN)
|
||||||
|
|
||||||
|
|
|
@ -32,6 +32,12 @@ class WalletTest (BitcoinTestFramework):
|
||||||
self.sync_all()
|
self.sync_all()
|
||||||
|
|
||||||
def run_test (self):
|
def run_test (self):
|
||||||
|
|
||||||
|
# Check that there's no UTXO on none of the nodes
|
||||||
|
assert_equal(len(self.nodes[0].listunspent()), 0)
|
||||||
|
assert_equal(len(self.nodes[1].listunspent()), 0)
|
||||||
|
assert_equal(len(self.nodes[2].listunspent()), 0)
|
||||||
|
|
||||||
print "Mining blocks..."
|
print "Mining blocks..."
|
||||||
|
|
||||||
self.nodes[0].generate(1)
|
self.nodes[0].generate(1)
|
||||||
|
@ -48,6 +54,11 @@ class WalletTest (BitcoinTestFramework):
|
||||||
assert_equal(self.nodes[1].getbalance(), 50)
|
assert_equal(self.nodes[1].getbalance(), 50)
|
||||||
assert_equal(self.nodes[2].getbalance(), 0)
|
assert_equal(self.nodes[2].getbalance(), 0)
|
||||||
|
|
||||||
|
# Check that only first and second nodes have UTXOs
|
||||||
|
assert_equal(len(self.nodes[0].listunspent()), 1)
|
||||||
|
assert_equal(len(self.nodes[1].listunspent()), 1)
|
||||||
|
assert_equal(len(self.nodes[2].listunspent()), 0)
|
||||||
|
|
||||||
# Send 21 BTC from 0 to 2 using sendtoaddress call.
|
# Send 21 BTC from 0 to 2 using sendtoaddress call.
|
||||||
self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 11)
|
self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 11)
|
||||||
self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 10)
|
self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 10)
|
||||||
|
@ -259,6 +270,32 @@ class WalletTest (BitcoinTestFramework):
|
||||||
except JSONRPCException as e:
|
except JSONRPCException as e:
|
||||||
assert("not an integer" in e.error['message'])
|
assert("not an integer" in e.error['message'])
|
||||||
|
|
||||||
|
# Import address and private key to check correct behavior of spendable unspents
|
||||||
|
# 1. Send some coins to generate new UTXO
|
||||||
|
address_to_import = self.nodes[2].getnewaddress()
|
||||||
|
txid = self.nodes[0].sendtoaddress(address_to_import, 1)
|
||||||
|
self.nodes[0].generate(1)
|
||||||
|
self.sync_all()
|
||||||
|
|
||||||
|
# 2. Import address from node2 to node1
|
||||||
|
self.nodes[1].importaddress(address_to_import)
|
||||||
|
|
||||||
|
# 3. Validate that the imported address is watch-only on node1
|
||||||
|
assert(self.nodes[1].validateaddress(address_to_import)["iswatchonly"])
|
||||||
|
|
||||||
|
# 4. Check that the unspents after import are not spendable
|
||||||
|
assert_array_result(self.nodes[1].listunspent(),
|
||||||
|
{"address": address_to_import},
|
||||||
|
{"spendable": False})
|
||||||
|
|
||||||
|
# 5. Import private key of the previously imported address on node1
|
||||||
|
priv_key = self.nodes[2].dumpprivkey(address_to_import)
|
||||||
|
self.nodes[1].importprivkey(priv_key)
|
||||||
|
|
||||||
|
# 6. Check that the unspents are now spendable on node1
|
||||||
|
assert_array_result(self.nodes[1].listunspent(),
|
||||||
|
{"address": address_to_import},
|
||||||
|
{"spendable": True})
|
||||||
|
|
||||||
# Mine a block from node0 to an address from node1
|
# Mine a block from node0 to an address from node1
|
||||||
cbAddr = self.nodes[1].getnewaddress()
|
cbAddr = self.nodes[1].getnewaddress()
|
||||||
|
|
Loading…
Reference in a new issue