Merge pull request #5542 from LarryRuane/2022-02-z_listreceivedbyaddress-ua-1

fix wallet_listreceived.py, add blockdata to taddr output
This commit is contained in:
Kris Nuttycombe 2022-02-12 14:59:08 -07:00 committed by GitHub
commit e6d3dca2a3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 84 additions and 134 deletions

View File

@ -36,12 +36,14 @@ class ListReceivedTest (BitcoinTestFramework):
extra_args=[['-experimentalfeatures', '-orchardwallet']] * self.num_nodes) extra_args=[['-experimentalfeatures', '-orchardwallet']] * self.num_nodes)
connect_nodes_bi(self.nodes, 0, 1) connect_nodes_bi(self.nodes, 0, 1)
connect_nodes_bi(self.nodes, 1, 2) connect_nodes_bi(self.nodes, 1, 2)
connect_nodes_bi(self.nodes, 0, 2)
self.is_network_split = False self.is_network_split = False
self.sync_all() self.sync_all()
def generate_and_sync(self, new_height): def generate_and_sync(self, new_height):
current_height = self.nodes[0].getblockcount() current_height = self.nodes[0].getblockcount()
assert(new_height > current_height) assert(new_height > current_height)
self.sync_all()
self.nodes[0].generate(new_height - current_height) self.nodes[0].generate(new_height - current_height)
self.sync_all() self.sync_all()
assert_equal(new_height, self.nodes[0].getblockcount()) assert_equal(new_height, self.nodes[0].getblockcount())
@ -186,9 +188,8 @@ class ListReceivedTest (BitcoinTestFramework):
# zaddr1 should have a note with change # zaddr1 should have a note with change
r = self.nodes[1].z_listreceivedbyaddress(zaddr1, 0) r = self.nodes[1].z_listreceivedbyaddress(zaddr1, 0)
r = sorted(r, key = lambda received: received['amount'])
assert_equal(2, len(r), "zaddr1 Should have received 2 notes") assert_equal(2, len(r), "zaddr1 Should have received 2 notes")
r = sorted(r, key = lambda received: received['amount'])
assert_equal(txid, r[0]['txid']) assert_equal(txid, r[0]['txid'])
assert_equal(Decimal('9.4')-DEFAULT_FEE, r[0]['amount']) assert_equal(Decimal('9.4')-DEFAULT_FEE, r[0]['amount'])
assert_equal(940000000-DEFAULT_FEE_ZATS, r[0]['amountZat']) assert_equal(940000000-DEFAULT_FEE_ZATS, r[0]['amountZat'])
@ -225,53 +226,25 @@ class ListReceivedTest (BitcoinTestFramework):
assert_equal(len(pt['spends']), 0) assert_equal(len(pt['spends']), 0)
assert_equal(len(pt['outputs']), 2) assert_equal(len(pt['outputs']), 2)
# Expect one internal output and one external. # Outputs are not returned in a defined order but the amounts are deterministic
assert_equal(len([output for output in pt['outputs'] if output['outgoing']]), 1) outputs = sorted(pt['outputs'], key=lambda x: x['valueZat'])
assert_equal(outputs[0]['type'], 'sapling')
assert_equal(outputs[0]['address'], zaddr1)
assert_equal(outputs[0]['value'], Decimal('1'))
assert_equal(outputs[0]['valueZat'], 100000000)
assert_equal(outputs[0]['output'], 0)
assert_equal(outputs[0]['outgoing'], False)
assert_equal(outputs[0]['memo'], my_memo)
assert_equal(outputs[0]['memoStr'], my_memo_str)
# Outputs are not returned in a defined order so we check the output assert_equal(outputs[1]['type'], 'sapling')
# positions and contents separately assert_equal(outputs[1]['address'], zaddrExt)
outputs = [] assert_equal(outputs[1]['value'], Decimal('2'))
assert_equal(outputs[1]['valueZat'], 200000000)
assert_equal(pt['outputs'][0]['type'], 'sapling') assert_equal(outputs[1]['output'], 1)
if pt['outputs'][0]['address'] == zaddr1: assert_equal(outputs[1]['outgoing'], True)
assert_false('jsOutput' in pt['outputs'][0]) assert_equal(outputs[1]['memo'], no_memo)
assert_equal(pt['outputs'][0]['outgoing'], False) assert 'memoStr' not in outputs[1]
assert_equal(pt['outputs'][0]['memoStr'], my_memo_str)
else:
assert_equal(pt['outputs'][0]['outgoing'], True)
outputs.append({
'address': pt['outputs'][0]['address'],
'value': pt['outputs'][0]['value'],
'valueZat': pt['outputs'][0]['valueZat'],
'memo': pt['outputs'][0]['memo'],
})
assert_equal(pt['outputs'][1]['type'], 'sapling')
if pt['outputs'][1]['address'] == zaddr1:
assert_equal(pt['outputs'][1]['outgoing'], False)
assert_equal(pt['outputs'][1]['memoStr'], my_memo_str)
else:
assert_equal(pt['outputs'][1]['outgoing'], True)
outputs.append({
'address': pt['outputs'][1]['address'],
'value': pt['outputs'][1]['value'],
'valueZat': pt['outputs'][1]['valueZat'],
'memo': pt['outputs'][1]['memo'],
})
assert({
'address': zaddr1,
'value': Decimal('1'),
'valueZat': 100000000,
'memo': my_memo,
} in outputs)
assert({
'address': zaddrExt,
'value': Decimal('2'),
'valueZat': 200000000,
'memo': no_memo,
} in outputs)
r = self.nodes[1].z_listreceivedbyaddress(zaddr1) r = self.nodes[1].z_listreceivedbyaddress(zaddr1)
assert_equal(0, len(r), "Should have received no confirmed note") assert_equal(0, len(r), "Should have received no confirmed note")
@ -329,72 +302,55 @@ class ListReceivedTest (BitcoinTestFramework):
assert_equal(pt['spends'][0]['value'], Decimal('1.0')) assert_equal(pt['spends'][0]['value'], Decimal('1.0'))
assert_equal(pt['spends'][0]['valueZat'], 100000000) assert_equal(pt['spends'][0]['valueZat'], 100000000)
# Outputs are not returned in a defined order so we check the output # Outputs are not returned in a defined order but the amounts are deterministic
# positions and contents separately outputs = sorted(pt['outputs'], key=lambda x: x['valueZat'])
outputs = [] assert_equal(outputs[0]['type'], 'sapling')
assert_equal(outputs[0]['address'], zaddr1)
assert_equal(outputs[0]['value'], Decimal('0.4') - DEFAULT_FEE)
assert_equal(outputs[0]['valueZat'], 40000000 - DEFAULT_FEE_ZATS)
assert_equal(outputs[0]['output'], 1)
assert_equal(outputs[0]['outgoing'], False)
assert_equal(outputs[0]['memo'], no_memo)
assert 'memoStr' not in outputs[0]
assert_equal(pt['outputs'][0]['type'], 'sapling') assert_equal(outputs[1]['type'], 'sapling')
assert_equal(pt['outputs'][0]['output'], 0) assert_equal(outputs[1]['address'], zaddr2)
assert_equal(pt['outputs'][0]['outgoing'], False) assert_equal(outputs[1]['value'], Decimal('0.6'))
outputs.append({ assert_equal(outputs[1]['valueZat'], 60000000)
'address': pt['outputs'][0]['address'], assert_equal(outputs[1]['output'], 0)
'value': pt['outputs'][0]['value'], assert_equal(outputs[1]['outgoing'], False)
'valueZat': pt['outputs'][0]['valueZat'], assert_equal(outputs[1]['memo'], no_memo)
'memo': pt['outputs'][0]['memo'], assert 'memoStr' not in outputs[1]
})
assert_equal(pt['outputs'][1]['type'], 'sapling')
assert_equal(pt['outputs'][1]['output'], 1)
assert_equal(pt['outputs'][1]['outgoing'], False)
outputs.append({
'address': pt['outputs'][1]['address'],
'value': pt['outputs'][1]['value'],
'valueZat': pt['outputs'][1]['valueZat'],
'memo': pt['outputs'][1]['memo'],
})
assert({
'address': zaddr2,
'value': Decimal('0.6'),
'valueZat': 60000000,
'memo': no_memo,
} in outputs)
assert({
'address': zaddr1,
'value': Decimal('0.4') - DEFAULT_FEE,
'valueZat': 40000000 - DEFAULT_FEE_ZATS,
'memo': no_memo,
} in outputs)
# zaddr1 should have a note with change # zaddr1 should have a note with change
r = self.nodes[1].z_listreceivedbyaddress(zaddr1, 0) r = self.nodes[1].z_listreceivedbyaddress(zaddr1, 0)
r = sorted(r, key = lambda received: received['amount'])
assert_equal(2, len(r), "zaddr1 Should have received 2 notes") assert_equal(2, len(r), "zaddr1 Should have received 2 notes")
r = sorted(r, key = lambda received: received['amount'])
assert_equal(txid, r[0]['txid']) assert_equal(txid, r[0]['txid'])
assert_equal(Decimal('0.4')-DEFAULT_FEE, r[0]['amount']) assert_equal(Decimal('0.4')-DEFAULT_FEE, r[0]['amount'])
assert_equal(40000000-DEFAULT_FEE_ZATS, r[0]['amountZat']) assert_equal(40000000-DEFAULT_FEE_ZATS, r[0]['amountZat'])
assert_true(r[0]['change'], "Note valued at (0.4-"+str(DEFAULT_FEE)+") should be change") assert_equal(r[0]['change'], True, "Note valued at (0.4-"+str(DEFAULT_FEE)+") should be change")
assert_equal(no_memo, r[0]['memo']) assert_equal(no_memo, r[0]['memo'])
# The old note still exists (it's immutable), even though it is spent # The old note still exists (it's immutable), even though it is spent
assert_equal(Decimal('1.0'), r[1]['amount']) assert_equal(Decimal('1.0'), r[1]['amount'])
assert_equal(100000000, r[1]['amountZat']) assert_equal(100000000, r[1]['amountZat'])
assert_false(r[1]['change'], "Note valued at 1.0 should not be change") assert_equal(r[1]['change'], False, "Note valued at 1.0 should not be change")
assert_equal(my_memo, r[1]['memo']) assert_equal(my_memo, r[1]['memo'])
# zaddr2 should not have change # zaddr2 should not have change
r = self.nodes[1].z_listreceivedbyaddress(zaddr2, 0) r = self.nodes[1].z_listreceivedbyaddress(zaddr2, 0)
assert_equal(len(r), 1, "zaddr2 Should have received 1 notes")
r = sorted(r, key = lambda received: received['amount']) r = sorted(r, key = lambda received: received['amount'])
assert_equal(1, len(r), "zaddr2 Should have received 1 notes") assert_equal(r[0]['txid'], txid)
assert_equal(txid, r[0]['txid']) assert_equal(r[0]['amount'], Decimal('0.6'))
assert_equal(Decimal('0.6'), r[0]['amount']) assert_equal(r[0]['amountZat'], 60000000)
assert_equal(60000000, r[0]['amountZat']) assert_equal(r[0]['change'], False, "Note valued at 0.6 should not be change")
assert_false(r[0]['change'], "Note valued at 0.6 should not be change") assert_equal(r[0]['memo'], no_memo)
assert_equal(no_memo, r[0]['memo']) assert 0 <= r[0]['outindex'] < 2
c = self.nodes[1].z_getnotescount(0) c = self.nodes[1].z_getnotescount(0)
assert_equal(3, c['sapling'], "Count of unconfirmed notes should be 3(2 in zaddr1 + 1 in zaddr2)") assert_equal(c['sapling'], 3, "Count of unconfirmed notes should be 3(2 in zaddr1 + 1 in zaddr2)")
# As part of UA support, a transparent address is now accepted # As part of UA support, a transparent address is now accepted
r = self.nodes[1].z_listreceivedbyaddress(taddr, 0) r = self.nodes[1].z_listreceivedbyaddress(taddr, 0)
@ -404,7 +360,7 @@ class ListReceivedTest (BitcoinTestFramework):
assert_equal(r[0]['amount'], Decimal('4')) assert_equal(r[0]['amount'], Decimal('4'))
assert_equal(r[0]['amountZat'], 400000000) assert_equal(r[0]['amountZat'], 400000000)
assert_equal(r[0]['confirmations'], 3) assert_equal(r[0]['confirmations'], 3)
assert r[0]['outindex'] < 2 assert 0 <= r[0]['outindex'] < 2
# Test unified address # Test unified address
node = self.nodes[1] node = self.nodes[1]
@ -443,44 +399,31 @@ class ListReceivedTest (BitcoinTestFramework):
r = node.z_listreceivedbyaddress(unified_addr, 0) r = node.z_listreceivedbyaddress(unified_addr, 0)
assert_equal(len(r), 2, "unified_addr should have received 2 payments") assert_equal(len(r), 2, "unified_addr should have received 2 payments")
print(r) # The return list order isn't defined, so sort by pool name
outputs = []; r = sorted(r, key=lambda x: x['pool'])
outputs.append({ assert_equal(r[0]['pool'], 'sapling')
'pool': r[0]['pool'], assert_equal(r[0]['txid'], txid_sapling)
'txid': r[0]['txid'], assert_equal(r[0]['amount'], Decimal('0.1'))
'amount': r[0]['amount'], assert_equal(r[0]['amountZat'], 10000000)
'amountZat': r[0]['amountZat'], assert_equal(r[0]['memo'], no_memo)
'change': r[0]['change'] if 'change' in r[0] else None, assert 0 <= r[0]['outindex'] < 2
'memo': r[0]['memo'] if 'memo' in r[0] else None, assert_equal(r[0]['confirmations'], 1)
'confirmations': r[0]['confirmations'] assert_equal(r[0]['change'], False)
}) assert_equal(r[0]['blockheight'], height+5)
outputs.append({ assert_equal(r[0]['blockindex'], 1)
'pool': r[1]['pool'], assert 'blocktime' in r[0]
'txid': r[1]['txid'],
'amount': r[1]['amount'], assert_equal(r[1]['pool'], 'transparent')
'amountZat': r[1]['amountZat'], assert_equal(r[1]['txid'], txid_taddr)
'change': r[1]['change'] if 'change' in r[1] else None, assert_equal(r[1]['amount'], Decimal('0.2'))
'memo': r[1]['memo'] if 'memo' in r[1] else None, assert_equal(r[1]['amountZat'], 20000000)
'confirmations': r[1]['confirmations'] assert 0 <= r[1]['outindex'] < 2
}) assert_equal(r[1]['confirmations'], 0)
assert({ assert_equal(r[1]['change'], False)
'pool': 'sapling', assert 'memo' not in r[1]
'txid': txid_sapling, assert_equal(r[1]['blockheight'], 0) # not yet mined
'amount': Decimal('0.1'), assert_equal(r[1]['blockindex'], -1) # not yet mined
'amountZat': 10000000, assert 'blocktime' in r[1]
'change': False,
'memo': no_memo,
'confirmations': 0,
} in outputs)
assert({
'pool': 'transparent',
'txid': txid_taddr,
'amount': Decimal('0.2'),
'amountZat': 20000000,
'change': False,
'memo': None,
'confirmations': 0,
} in outputs)
def run_test(self): def run_test(self):
self.test_received_sprout(200) self.test_received_sprout(200)

View File

@ -3492,13 +3492,20 @@ UniValue z_listreceivedbyaddress(const UniValue& params, bool fHelp)
const CTxOut& txout{wtx.vout[i]}; const CTxOut& txout{wtx.vout[i]};
if (txout.scriptPubKey == scriptPubKey) { if (txout.scriptPubKey == scriptPubKey) {
UniValue obj(UniValue::VOBJ); UniValue obj(UniValue::VOBJ);
auto txid{wtx.GetHash()};
obj.pushKV("pool", "transparent"); obj.pushKV("pool", "transparent");
obj.pushKV("txid", wtx.GetHash().ToString()); obj.pushKV("txid", txid.ToString());
obj.pushKV("amount", ValueFromAmount(txout.nValue)); obj.pushKV("amount", ValueFromAmount(txout.nValue));
obj.pushKV("amountZat", txout.nValue); obj.pushKV("amountZat", txout.nValue);
obj.pushKV("outindex", int(i)); obj.pushKV("outindex", int(i));
obj.pushKV("confirmations", nDepth); obj.pushKV("confirmations", nDepth);
obj.pushKV("change", pwalletMain->IsChange(txout)); obj.pushKV("change", pwalletMain->IsChange(txout));
txblock BlockData(txid);
obj.pushKV("blockheight", BlockData.height);
obj.pushKV("blockindex", BlockData.index);
obj.pushKV("blocktime", BlockData.time);
result.push_back(obj); result.push_back(obj);
} }
} }