Bitcore port
This commit is contained in:
@@ -35,6 +35,9 @@ testScripts=(
|
||||
'walletbackup.py'
|
||||
'nodehandling.py'
|
||||
'reindex.py'
|
||||
'addressindex.py'
|
||||
'timestampindex.py'
|
||||
'spentindex.py'
|
||||
'decodescript.py'
|
||||
'disablewallet.py'
|
||||
'zcjoinsplit.py'
|
||||
|
||||
349
qa/rpc-tests/addressindex.py
Normal file
349
qa/rpc-tests/addressindex.py
Normal file
@@ -0,0 +1,349 @@
|
||||
#!/usr/bin/env python2
|
||||
# Copyright (c) 2014-2015 The Bitcoin Core developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#
|
||||
# Test addressindex generation and fetching
|
||||
#
|
||||
|
||||
import time
|
||||
from test_framework.test_framework import BitcoinTestFramework
|
||||
from test_framework.util import *
|
||||
from test_framework.script import *
|
||||
from test_framework.mininode import *
|
||||
import binascii
|
||||
|
||||
class AddressIndexTest(BitcoinTestFramework):
|
||||
|
||||
def setup_chain(self):
|
||||
print("Initializing test directory "+self.options.tmpdir)
|
||||
initialize_chain_clean(self.options.tmpdir, 4)
|
||||
|
||||
def setup_network(self):
|
||||
self.nodes = []
|
||||
# Nodes 0/1 are "wallet" nodes
|
||||
self.nodes.append(start_node(0, self.options.tmpdir, ["-debug", "-relaypriority=0"]))
|
||||
self.nodes.append(start_node(1, self.options.tmpdir, ["-debug", "-addressindex"]))
|
||||
# Nodes 2/3 are used for testing
|
||||
self.nodes.append(start_node(2, self.options.tmpdir, ["-debug", "-addressindex", "-relaypriority=0"]))
|
||||
self.nodes.append(start_node(3, self.options.tmpdir, ["-debug", "-addressindex"]))
|
||||
connect_nodes(self.nodes[0], 1)
|
||||
connect_nodes(self.nodes[0], 2)
|
||||
connect_nodes(self.nodes[0], 3)
|
||||
|
||||
self.is_network_split = False
|
||||
self.sync_all()
|
||||
|
||||
def run_test(self):
|
||||
print "Mining blocks..."
|
||||
self.nodes[0].generate(105)
|
||||
self.sync_all()
|
||||
|
||||
chain_height = self.nodes[1].getblockcount()
|
||||
assert_equal(chain_height, 105)
|
||||
assert_equal(self.nodes[1].getbalance(), 0)
|
||||
assert_equal(self.nodes[2].getbalance(), 0)
|
||||
|
||||
# Check that balances are correct
|
||||
balance0 = self.nodes[1].getaddressbalance("2N2JD6wb56AfK4tfmM6PwdVmoYk2dCKf4Br")
|
||||
assert_equal(balance0["balance"], 0)
|
||||
|
||||
# Check p2pkh and p2sh address indexes
|
||||
print "Testing p2pkh and p2sh address index..."
|
||||
|
||||
txid0 = self.nodes[0].sendtoaddress("mo9ncXisMeAoXwqcV5EWuyncbmCcQN4rVs", 10)
|
||||
self.nodes[0].generate(1)
|
||||
|
||||
txidb0 = self.nodes[0].sendtoaddress("2N2JD6wb56AfK4tfmM6PwdVmoYk2dCKf4Br", 10)
|
||||
self.nodes[0].generate(1)
|
||||
|
||||
txid1 = self.nodes[0].sendtoaddress("mo9ncXisMeAoXwqcV5EWuyncbmCcQN4rVs", 15)
|
||||
self.nodes[0].generate(1)
|
||||
|
||||
txidb1 = self.nodes[0].sendtoaddress("2N2JD6wb56AfK4tfmM6PwdVmoYk2dCKf4Br", 15)
|
||||
self.nodes[0].generate(1)
|
||||
|
||||
txid2 = self.nodes[0].sendtoaddress("mo9ncXisMeAoXwqcV5EWuyncbmCcQN4rVs", 20)
|
||||
self.nodes[0].generate(1)
|
||||
|
||||
txidb2 = self.nodes[0].sendtoaddress("2N2JD6wb56AfK4tfmM6PwdVmoYk2dCKf4Br", 20)
|
||||
self.nodes[0].generate(1)
|
||||
|
||||
self.sync_all()
|
||||
|
||||
txids = self.nodes[1].getaddresstxids("mo9ncXisMeAoXwqcV5EWuyncbmCcQN4rVs")
|
||||
assert_equal(len(txids), 3)
|
||||
assert_equal(txids[0], txid0)
|
||||
assert_equal(txids[1], txid1)
|
||||
assert_equal(txids[2], txid2)
|
||||
|
||||
txidsb = self.nodes[1].getaddresstxids("2N2JD6wb56AfK4tfmM6PwdVmoYk2dCKf4Br")
|
||||
assert_equal(len(txidsb), 3)
|
||||
assert_equal(txidsb[0], txidb0)
|
||||
assert_equal(txidsb[1], txidb1)
|
||||
assert_equal(txidsb[2], txidb2)
|
||||
|
||||
# Check that limiting by height works
|
||||
print "Testing querying txids by range of block heights.."
|
||||
height_txids = self.nodes[1].getaddresstxids({
|
||||
"addresses": ["2N2JD6wb56AfK4tfmM6PwdVmoYk2dCKf4Br"],
|
||||
"start": 105,
|
||||
"end": 110
|
||||
})
|
||||
assert_equal(len(height_txids), 2)
|
||||
assert_equal(height_txids[0], txidb0)
|
||||
assert_equal(height_txids[1], txidb1)
|
||||
|
||||
# Check that multiple addresses works
|
||||
multitxids = self.nodes[1].getaddresstxids({"addresses": ["2N2JD6wb56AfK4tfmM6PwdVmoYk2dCKf4Br", "mo9ncXisMeAoXwqcV5EWuyncbmCcQN4rVs"]})
|
||||
assert_equal(len(multitxids), 6)
|
||||
assert_equal(multitxids[0], txid0)
|
||||
assert_equal(multitxids[1], txidb0)
|
||||
assert_equal(multitxids[2], txid1)
|
||||
assert_equal(multitxids[3], txidb1)
|
||||
assert_equal(multitxids[4], txid2)
|
||||
assert_equal(multitxids[5], txidb2)
|
||||
|
||||
# Check that balances are correct
|
||||
balance0 = self.nodes[1].getaddressbalance("2N2JD6wb56AfK4tfmM6PwdVmoYk2dCKf4Br")
|
||||
assert_equal(balance0["balance"], 45 * 100000000)
|
||||
|
||||
# Check that outputs with the same address will only return one txid
|
||||
print "Testing for txid uniqueness..."
|
||||
addressHash = "6349a418fc4578d10a372b54b45c280cc8c4382f".decode("hex")
|
||||
scriptPubKey = CScript([OP_HASH160, addressHash, OP_EQUAL])
|
||||
unspent = self.nodes[0].listunspent()
|
||||
tx = CTransaction()
|
||||
tx.vin = [CTxIn(COutPoint(int(unspent[0]["txid"], 16), unspent[0]["vout"]))]
|
||||
tx.vout = [CTxOut(10, scriptPubKey), CTxOut(11, scriptPubKey)]
|
||||
tx.rehash()
|
||||
|
||||
signed_tx = self.nodes[0].signrawtransaction(binascii.hexlify(tx.serialize()).decode("utf-8"))
|
||||
sent_txid = self.nodes[0].sendrawtransaction(signed_tx["hex"], True)
|
||||
|
||||
self.nodes[0].generate(1)
|
||||
self.sync_all()
|
||||
|
||||
txidsmany = self.nodes[1].getaddresstxids("2N2JD6wb56AfK4tfmM6PwdVmoYk2dCKf4Br")
|
||||
assert_equal(len(txidsmany), 4)
|
||||
assert_equal(txidsmany[3], sent_txid)
|
||||
|
||||
# Check that balances are correct
|
||||
print "Testing balances..."
|
||||
balance0 = self.nodes[1].getaddressbalance("2N2JD6wb56AfK4tfmM6PwdVmoYk2dCKf4Br")
|
||||
assert_equal(balance0["balance"], 45 * 100000000 + 21)
|
||||
|
||||
# Check that balances are correct after spending
|
||||
print "Testing balances after spending..."
|
||||
privkey2 = "cSdkPxkAjA4HDr5VHgsebAPDEh9Gyub4HK8UJr2DFGGqKKy4K5sG"
|
||||
address2 = "mgY65WSfEmsyYaYPQaXhmXMeBhwp4EcsQW"
|
||||
addressHash2 = "0b2f0a0c31bfe0406b0ccc1381fdbe311946dadc".decode("hex")
|
||||
scriptPubKey2 = CScript([OP_DUP, OP_HASH160, addressHash2, OP_EQUALVERIFY, OP_CHECKSIG])
|
||||
self.nodes[0].importprivkey(privkey2)
|
||||
|
||||
unspent = self.nodes[0].listunspent()
|
||||
tx = CTransaction()
|
||||
tx.vin = [CTxIn(COutPoint(int(unspent[0]["txid"], 16), unspent[0]["vout"]))]
|
||||
amount = unspent[0]["amount"] * 100000000
|
||||
tx.vout = [CTxOut(amount, scriptPubKey2)]
|
||||
tx.rehash()
|
||||
signed_tx = self.nodes[0].signrawtransaction(binascii.hexlify(tx.serialize()).decode("utf-8"))
|
||||
spending_txid = self.nodes[0].sendrawtransaction(signed_tx["hex"], True)
|
||||
self.nodes[0].generate(1)
|
||||
self.sync_all()
|
||||
balance1 = self.nodes[1].getaddressbalance(address2)
|
||||
assert_equal(balance1["balance"], amount)
|
||||
|
||||
tx = CTransaction()
|
||||
tx.vin = [CTxIn(COutPoint(int(spending_txid, 16), 0))]
|
||||
send_amount = 1 * 100000000 + 12840
|
||||
change_amount = amount - send_amount - 10000
|
||||
tx.vout = [CTxOut(change_amount, scriptPubKey2), CTxOut(send_amount, scriptPubKey)]
|
||||
tx.rehash()
|
||||
|
||||
signed_tx = self.nodes[0].signrawtransaction(binascii.hexlify(tx.serialize()).decode("utf-8"))
|
||||
sent_txid = self.nodes[0].sendrawtransaction(signed_tx["hex"], True)
|
||||
self.nodes[0].generate(1)
|
||||
self.sync_all()
|
||||
|
||||
balance2 = self.nodes[1].getaddressbalance(address2)
|
||||
assert_equal(balance2["balance"], change_amount)
|
||||
|
||||
# Check that deltas are returned correctly
|
||||
deltas = self.nodes[1].getaddressdeltas({"addresses": [address2], "start": 1, "end": 200})
|
||||
balance3 = 0
|
||||
for delta in deltas:
|
||||
balance3 += delta["satoshis"]
|
||||
assert_equal(balance3, change_amount)
|
||||
assert_equal(deltas[0]["address"], address2)
|
||||
assert_equal(deltas[0]["blockindex"], 1)
|
||||
|
||||
# Check that entire range will be queried
|
||||
deltasAll = self.nodes[1].getaddressdeltas({"addresses": [address2]})
|
||||
assert_equal(len(deltasAll), len(deltas))
|
||||
|
||||
# Check that deltas can be returned from range of block heights
|
||||
deltas = self.nodes[1].getaddressdeltas({"addresses": [address2], "start": 113, "end": 113})
|
||||
assert_equal(len(deltas), 1)
|
||||
|
||||
# Check that unspent outputs can be queried
|
||||
print "Testing utxos..."
|
||||
utxos = self.nodes[1].getaddressutxos({"addresses": [address2]})
|
||||
assert_equal(len(utxos), 1)
|
||||
assert_equal(utxos[0]["satoshis"], change_amount)
|
||||
|
||||
# Check that indexes will be updated with a reorg
|
||||
print "Testing reorg..."
|
||||
|
||||
best_hash = self.nodes[0].getbestblockhash()
|
||||
self.nodes[0].invalidateblock(best_hash)
|
||||
self.nodes[1].invalidateblock(best_hash)
|
||||
self.nodes[2].invalidateblock(best_hash)
|
||||
self.nodes[3].invalidateblock(best_hash)
|
||||
self.sync_all()
|
||||
|
||||
balance4 = self.nodes[1].getaddressbalance(address2)
|
||||
assert_equal(balance4, balance1)
|
||||
|
||||
utxos2 = self.nodes[1].getaddressutxos({"addresses": [address2]})
|
||||
assert_equal(len(utxos2), 1)
|
||||
assert_equal(utxos2[0]["satoshis"], amount)
|
||||
|
||||
# Check sorting of utxos
|
||||
self.nodes[2].generate(150)
|
||||
|
||||
txidsort1 = self.nodes[2].sendtoaddress(address2, 50)
|
||||
self.nodes[2].generate(1)
|
||||
txidsort2 = self.nodes[2].sendtoaddress(address2, 50)
|
||||
self.nodes[2].generate(1)
|
||||
self.sync_all()
|
||||
|
||||
utxos3 = self.nodes[1].getaddressutxos({"addresses": [address2]})
|
||||
assert_equal(len(utxos3), 3)
|
||||
assert_equal(utxos3[0]["height"], 114)
|
||||
assert_equal(utxos3[1]["height"], 264)
|
||||
assert_equal(utxos3[2]["height"], 265)
|
||||
|
||||
# Check mempool indexing
|
||||
print "Testing mempool indexing..."
|
||||
|
||||
privKey3 = "cVfUn53hAbRrDEuMexyfgDpZPhF7KqXpS8UZevsyTDaugB7HZ3CD"
|
||||
address3 = "mw4ynwhS7MmrQ27hr82kgqu7zryNDK26JB"
|
||||
addressHash3 = "aa9872b5bbcdb511d89e0e11aa27da73fd2c3f50".decode("hex")
|
||||
scriptPubKey3 = CScript([OP_DUP, OP_HASH160, addressHash3, OP_EQUALVERIFY, OP_CHECKSIG])
|
||||
address4 = "2N8oFVB2vThAKury4vnLquW2zVjsYjjAkYQ"
|
||||
scriptPubKey4 = CScript([OP_HASH160, addressHash3, OP_EQUAL])
|
||||
unspent = self.nodes[2].listunspent()
|
||||
|
||||
tx = CTransaction()
|
||||
tx.vin = [CTxIn(COutPoint(int(unspent[0]["txid"], 16), unspent[0]["vout"]))]
|
||||
amount = unspent[0]["amount"] * 100000000
|
||||
tx.vout = [CTxOut(amount, scriptPubKey3)]
|
||||
tx.rehash()
|
||||
signed_tx = self.nodes[2].signrawtransaction(binascii.hexlify(tx.serialize()).decode("utf-8"))
|
||||
memtxid1 = self.nodes[2].sendrawtransaction(signed_tx["hex"], True)
|
||||
time.sleep(2)
|
||||
|
||||
tx2 = CTransaction()
|
||||
tx2.vin = [CTxIn(COutPoint(int(unspent[1]["txid"], 16), unspent[1]["vout"]))]
|
||||
amount = unspent[1]["amount"] * 100000000
|
||||
tx2.vout = [
|
||||
CTxOut(amount / 4, scriptPubKey3),
|
||||
CTxOut(amount / 4, scriptPubKey3),
|
||||
CTxOut(amount / 4, scriptPubKey4),
|
||||
CTxOut(amount / 4, scriptPubKey4)
|
||||
]
|
||||
tx2.rehash()
|
||||
signed_tx2 = self.nodes[2].signrawtransaction(binascii.hexlify(tx2.serialize()).decode("utf-8"))
|
||||
memtxid2 = self.nodes[2].sendrawtransaction(signed_tx2["hex"], True)
|
||||
time.sleep(2)
|
||||
|
||||
mempool = self.nodes[2].getaddressmempool({"addresses": [address3]})
|
||||
assert_equal(len(mempool), 3)
|
||||
assert_equal(mempool[0]["txid"], memtxid1)
|
||||
assert_equal(mempool[0]["address"], address3)
|
||||
assert_equal(mempool[0]["index"], 0)
|
||||
assert_equal(mempool[1]["txid"], memtxid2)
|
||||
assert_equal(mempool[1]["index"], 0)
|
||||
assert_equal(mempool[2]["txid"], memtxid2)
|
||||
assert_equal(mempool[2]["index"], 1)
|
||||
|
||||
self.nodes[2].generate(1);
|
||||
self.sync_all();
|
||||
mempool2 = self.nodes[2].getaddressmempool({"addresses": [address3]})
|
||||
assert_equal(len(mempool2), 0)
|
||||
|
||||
tx = CTransaction()
|
||||
tx.vin = [
|
||||
CTxIn(COutPoint(int(memtxid2, 16), 0)),
|
||||
CTxIn(COutPoint(int(memtxid2, 16), 1))
|
||||
]
|
||||
tx.vout = [CTxOut(amount / 2 - 10000, scriptPubKey2)]
|
||||
tx.rehash()
|
||||
self.nodes[2].importprivkey(privKey3)
|
||||
signed_tx3 = self.nodes[2].signrawtransaction(binascii.hexlify(tx.serialize()).decode("utf-8"))
|
||||
memtxid3 = self.nodes[2].sendrawtransaction(signed_tx3["hex"], True)
|
||||
time.sleep(2)
|
||||
|
||||
mempool3 = self.nodes[2].getaddressmempool({"addresses": [address3]})
|
||||
assert_equal(len(mempool3), 2)
|
||||
assert_equal(mempool3[0]["prevtxid"], memtxid2)
|
||||
assert_equal(mempool3[0]["prevout"], 0)
|
||||
assert_equal(mempool3[1]["prevtxid"], memtxid2)
|
||||
assert_equal(mempool3[1]["prevout"], 1)
|
||||
|
||||
# sending and receiving to the same address
|
||||
privkey1 = "cQY2s58LhzUCmEXN8jtAp1Etnijx78YRZ466w4ikX1V4UpTpbsf8"
|
||||
address1 = "myAUWSHnwsQrhuMWv4Br6QsCnpB41vFwHn"
|
||||
address1hash = "c192bff751af8efec15135d42bfeedf91a6f3e34".decode("hex")
|
||||
address1script = CScript([OP_DUP, OP_HASH160, address1hash, OP_EQUALVERIFY, OP_CHECKSIG])
|
||||
|
||||
self.nodes[0].sendtoaddress(address1, 10)
|
||||
self.nodes[0].generate(1)
|
||||
self.sync_all()
|
||||
|
||||
utxos = self.nodes[1].getaddressutxos({"addresses": [address1]})
|
||||
assert_equal(len(utxos), 1)
|
||||
|
||||
tx = CTransaction()
|
||||
tx.vin = [
|
||||
CTxIn(COutPoint(int(utxos[0]["txid"], 16), utxos[0]["outputIndex"]))
|
||||
]
|
||||
amount = utxos[0]["satoshis"] - 1000
|
||||
tx.vout = [CTxOut(amount, address1script)]
|
||||
tx.rehash()
|
||||
self.nodes[0].importprivkey(privkey1)
|
||||
signed_tx = self.nodes[0].signrawtransaction(binascii.hexlify(tx.serialize()).decode("utf-8"))
|
||||
mem_txid = self.nodes[0].sendrawtransaction(signed_tx["hex"], True)
|
||||
|
||||
self.sync_all()
|
||||
mempool_deltas = self.nodes[2].getaddressmempool({"addresses": [address1]})
|
||||
assert_equal(len(mempool_deltas), 2)
|
||||
|
||||
# Include chaininfo in results
|
||||
print "Testing results with chain info..."
|
||||
|
||||
deltas_with_info = self.nodes[1].getaddressdeltas({
|
||||
"addresses": [address2],
|
||||
"start": 1,
|
||||
"end": 200,
|
||||
"chainInfo": True
|
||||
})
|
||||
start_block_hash = self.nodes[1].getblockhash(1);
|
||||
end_block_hash = self.nodes[1].getblockhash(200);
|
||||
assert_equal(deltas_with_info["start"]["height"], 1)
|
||||
assert_equal(deltas_with_info["start"]["hash"], start_block_hash)
|
||||
assert_equal(deltas_with_info["end"]["height"], 200)
|
||||
assert_equal(deltas_with_info["end"]["hash"], end_block_hash)
|
||||
|
||||
utxos_with_info = self.nodes[1].getaddressutxos({"addresses": [address2], "chainInfo": True})
|
||||
expected_tip_block_hash = self.nodes[1].getblockhash(267);
|
||||
assert_equal(utxos_with_info["height"], 267)
|
||||
assert_equal(utxos_with_info["hash"], expected_tip_block_hash)
|
||||
|
||||
print "Passed\n"
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
AddressIndexTest().main()
|
||||
139
qa/rpc-tests/spentindex.py
Normal file
139
qa/rpc-tests/spentindex.py
Normal file
@@ -0,0 +1,139 @@
|
||||
#!/usr/bin/env python2
|
||||
# Copyright (c) 2014-2015 The Bitcoin Core developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#
|
||||
# Test addressindex generation and fetching
|
||||
#
|
||||
|
||||
import time
|
||||
from test_framework.test_framework import BitcoinTestFramework
|
||||
from test_framework.util import *
|
||||
from test_framework.script import *
|
||||
from test_framework.mininode import *
|
||||
import binascii
|
||||
|
||||
class SpentIndexTest(BitcoinTestFramework):
|
||||
|
||||
def setup_chain(self):
|
||||
print("Initializing test directory "+self.options.tmpdir)
|
||||
initialize_chain_clean(self.options.tmpdir, 4)
|
||||
|
||||
def setup_network(self):
|
||||
self.nodes = []
|
||||
# Nodes 0/1 are "wallet" nodes
|
||||
self.nodes.append(start_node(0, self.options.tmpdir, ["-debug"]))
|
||||
self.nodes.append(start_node(1, self.options.tmpdir, ["-debug", "-spentindex"]))
|
||||
# Nodes 2/3 are used for testing
|
||||
self.nodes.append(start_node(2, self.options.tmpdir, ["-debug", "-spentindex"]))
|
||||
self.nodes.append(start_node(3, self.options.tmpdir, ["-debug", "-spentindex", "-txindex"]))
|
||||
connect_nodes(self.nodes[0], 1)
|
||||
connect_nodes(self.nodes[0], 2)
|
||||
connect_nodes(self.nodes[0], 3)
|
||||
|
||||
self.is_network_split = False
|
||||
self.sync_all()
|
||||
|
||||
def run_test(self):
|
||||
print "Mining blocks..."
|
||||
self.nodes[0].generate(105)
|
||||
self.sync_all()
|
||||
|
||||
chain_height = self.nodes[1].getblockcount()
|
||||
assert_equal(chain_height, 105)
|
||||
|
||||
# Check that
|
||||
print "Testing spent index..."
|
||||
|
||||
privkey = "cSdkPxkAjA4HDr5VHgsebAPDEh9Gyub4HK8UJr2DFGGqKKy4K5sG"
|
||||
address = "mgY65WSfEmsyYaYPQaXhmXMeBhwp4EcsQW"
|
||||
addressHash = "0b2f0a0c31bfe0406b0ccc1381fdbe311946dadc".decode("hex")
|
||||
scriptPubKey = CScript([OP_DUP, OP_HASH160, addressHash, OP_EQUALVERIFY, OP_CHECKSIG])
|
||||
unspent = self.nodes[0].listunspent()
|
||||
tx = CTransaction()
|
||||
amount = unspent[0]["amount"] * 100000000
|
||||
tx.vin = [CTxIn(COutPoint(int(unspent[0]["txid"], 16), unspent[0]["vout"]))]
|
||||
tx.vout = [CTxOut(amount, scriptPubKey)]
|
||||
tx.rehash()
|
||||
|
||||
signed_tx = self.nodes[0].signrawtransaction(binascii.hexlify(tx.serialize()).decode("utf-8"))
|
||||
txid = self.nodes[0].sendrawtransaction(signed_tx["hex"], True)
|
||||
self.nodes[0].generate(1)
|
||||
self.sync_all()
|
||||
|
||||
print "Testing getspentinfo method..."
|
||||
|
||||
# Check that the spentinfo works standalone
|
||||
info = self.nodes[1].getspentinfo({"txid": unspent[0]["txid"], "index": unspent[0]["vout"]})
|
||||
assert_equal(info["txid"], txid)
|
||||
assert_equal(info["index"], 0)
|
||||
assert_equal(info["height"], 106)
|
||||
|
||||
print "Testing getrawtransaction method..."
|
||||
|
||||
# Check that verbose raw transaction includes spent info
|
||||
txVerbose = self.nodes[3].getrawtransaction(unspent[0]["txid"], 1)
|
||||
assert_equal(txVerbose["vout"][unspent[0]["vout"]]["spentTxId"], txid)
|
||||
assert_equal(txVerbose["vout"][unspent[0]["vout"]]["spentIndex"], 0)
|
||||
assert_equal(txVerbose["vout"][unspent[0]["vout"]]["spentHeight"], 106)
|
||||
|
||||
# Check that verbose raw transaction includes input values
|
||||
txVerbose2 = self.nodes[3].getrawtransaction(txid, 1)
|
||||
assert_equal(txVerbose2["vin"][0]["value"], Decimal(unspent[0]["amount"]))
|
||||
assert_equal(txVerbose2["vin"][0]["valueSat"], amount)
|
||||
|
||||
# Check that verbose raw transaction includes address values and input values
|
||||
privkey2 = "cSdkPxkAjA4HDr5VHgsebAPDEh9Gyub4HK8UJr2DFGGqKKy4K5sG"
|
||||
address2 = "mgY65WSfEmsyYaYPQaXhmXMeBhwp4EcsQW"
|
||||
addressHash2 = "0b2f0a0c31bfe0406b0ccc1381fdbe311946dadc".decode("hex")
|
||||
scriptPubKey2 = CScript([OP_DUP, OP_HASH160, addressHash2, OP_EQUALVERIFY, OP_CHECKSIG])
|
||||
tx2 = CTransaction()
|
||||
tx2.vin = [CTxIn(COutPoint(int(txid, 16), 0))]
|
||||
tx2.vout = [CTxOut(amount, scriptPubKey2)]
|
||||
tx.rehash()
|
||||
self.nodes[0].importprivkey(privkey)
|
||||
signed_tx2 = self.nodes[0].signrawtransaction(binascii.hexlify(tx2.serialize()).decode("utf-8"))
|
||||
txid2 = self.nodes[0].sendrawtransaction(signed_tx2["hex"], True)
|
||||
|
||||
# Check the mempool index
|
||||
self.sync_all()
|
||||
txVerbose3 = self.nodes[1].getrawtransaction(txid2, 1)
|
||||
assert_equal(txVerbose3["vin"][0]["address"], address2)
|
||||
assert_equal(txVerbose3["vin"][0]["value"], Decimal(unspent[0]["amount"]))
|
||||
assert_equal(txVerbose3["vin"][0]["valueSat"], amount)
|
||||
|
||||
# Check the database index
|
||||
block_hash = self.nodes[0].generate(1)
|
||||
self.sync_all()
|
||||
|
||||
txVerbose4 = self.nodes[3].getrawtransaction(txid2, 1)
|
||||
assert_equal(txVerbose4["vin"][0]["address"], address2)
|
||||
assert_equal(txVerbose4["vin"][0]["value"], Decimal(unspent[0]["amount"]))
|
||||
assert_equal(txVerbose4["vin"][0]["valueSat"], amount)
|
||||
|
||||
|
||||
# Check block deltas
|
||||
print "Testing getblockdeltas..."
|
||||
|
||||
block = self.nodes[3].getblockdeltas(block_hash[0])
|
||||
assert_equal(len(block["deltas"]), 2)
|
||||
assert_equal(block["deltas"][0]["index"], 0)
|
||||
assert_equal(len(block["deltas"][0]["inputs"]), 0)
|
||||
assert_equal(len(block["deltas"][0]["outputs"]), 0)
|
||||
assert_equal(block["deltas"][1]["index"], 1)
|
||||
assert_equal(block["deltas"][1]["txid"], txid2)
|
||||
assert_equal(block["deltas"][1]["inputs"][0]["index"], 0)
|
||||
assert_equal(block["deltas"][1]["inputs"][0]["address"], "mgY65WSfEmsyYaYPQaXhmXMeBhwp4EcsQW")
|
||||
assert_equal(block["deltas"][1]["inputs"][0]["satoshis"], amount * -1)
|
||||
assert_equal(block["deltas"][1]["inputs"][0]["prevtxid"], txid)
|
||||
assert_equal(block["deltas"][1]["inputs"][0]["prevout"], 0)
|
||||
assert_equal(block["deltas"][1]["outputs"][0]["index"], 0)
|
||||
assert_equal(block["deltas"][1]["outputs"][0]["address"], "mgY65WSfEmsyYaYPQaXhmXMeBhwp4EcsQW")
|
||||
assert_equal(block["deltas"][1]["outputs"][0]["satoshis"], amount)
|
||||
|
||||
print "Passed\n"
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
SpentIndexTest().main()
|
||||
61
qa/rpc-tests/timestampindex.py
Normal file
61
qa/rpc-tests/timestampindex.py
Normal file
@@ -0,0 +1,61 @@
|
||||
#!/usr/bin/env python2
|
||||
# Copyright (c) 2014-2015 The Bitcoin Core developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#
|
||||
# Test timestampindex generation and fetching
|
||||
#
|
||||
|
||||
import time
|
||||
|
||||
from test_framework.test_framework import BitcoinTestFramework
|
||||
from test_framework.util import *
|
||||
|
||||
|
||||
class TimestampIndexTest(BitcoinTestFramework):
|
||||
|
||||
def setup_chain(self):
|
||||
print("Initializing test directory "+self.options.tmpdir)
|
||||
initialize_chain_clean(self.options.tmpdir, 4)
|
||||
|
||||
def setup_network(self):
|
||||
self.nodes = []
|
||||
# Nodes 0/1 are "wallet" nodes
|
||||
self.nodes.append(start_node(0, self.options.tmpdir, ["-debug"]))
|
||||
self.nodes.append(start_node(1, self.options.tmpdir, ["-debug", "-timestampindex"]))
|
||||
# Nodes 2/3 are used for testing
|
||||
self.nodes.append(start_node(2, self.options.tmpdir, ["-debug"]))
|
||||
self.nodes.append(start_node(3, self.options.tmpdir, ["-debug", "-timestampindex"]))
|
||||
connect_nodes(self.nodes[0], 1)
|
||||
connect_nodes(self.nodes[0], 2)
|
||||
connect_nodes(self.nodes[0], 3)
|
||||
|
||||
self.is_network_split = False
|
||||
self.sync_all()
|
||||
|
||||
def run_test(self):
|
||||
print "Mining 25 blocks..."
|
||||
blockhashes = self.nodes[0].generate(25)
|
||||
time.sleep(3)
|
||||
print "Mining 25 blocks..."
|
||||
blockhashes.extend(self.nodes[0].generate(25))
|
||||
time.sleep(3)
|
||||
print "Mining 25 blocks..."
|
||||
blockhashes.extend(self.nodes[0].generate(25))
|
||||
self.sync_all()
|
||||
low = self.nodes[1].getblock(blockhashes[0])["time"]
|
||||
high = low + 76
|
||||
|
||||
print "Checking timestamp index..."
|
||||
hashes = self.nodes[1].getblockhashes(high, low)
|
||||
|
||||
assert_equal(len(hashes), len(blockhashes))
|
||||
|
||||
assert_equal(hashes, blockhashes)
|
||||
|
||||
print "Passed\n"
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
TimestampIndexTest().main()
|
||||
73
qa/rpc-tests/txindex.py
Normal file
73
qa/rpc-tests/txindex.py
Normal file
@@ -0,0 +1,73 @@
|
||||
#!/usr/bin/env python2
|
||||
# Copyright (c) 2014-2015 The Bitcoin Core developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#
|
||||
# Test txindex generation and fetching
|
||||
#
|
||||
|
||||
import time
|
||||
from test_framework.test_framework import BitcoinTestFramework
|
||||
from test_framework.util import *
|
||||
from test_framework.script import *
|
||||
from test_framework.mininode import *
|
||||
import binascii
|
||||
|
||||
class TxIndexTest(BitcoinTestFramework):
|
||||
|
||||
def setup_chain(self):
|
||||
print("Initializing test directory "+self.options.tmpdir)
|
||||
initialize_chain_clean(self.options.tmpdir, 4)
|
||||
|
||||
def setup_network(self):
|
||||
self.nodes = []
|
||||
# Nodes 0/1 are "wallet" nodes
|
||||
self.nodes.append(start_node(0, self.options.tmpdir, ["-debug"]))
|
||||
self.nodes.append(start_node(1, self.options.tmpdir, ["-debug", "-txindex"]))
|
||||
# Nodes 2/3 are used for testing
|
||||
self.nodes.append(start_node(2, self.options.tmpdir, ["-debug", "-txindex"]))
|
||||
self.nodes.append(start_node(3, self.options.tmpdir, ["-debug", "-txindex"]))
|
||||
connect_nodes(self.nodes[0], 1)
|
||||
connect_nodes(self.nodes[0], 2)
|
||||
connect_nodes(self.nodes[0], 3)
|
||||
|
||||
self.is_network_split = False
|
||||
self.sync_all()
|
||||
|
||||
def run_test(self):
|
||||
print "Mining blocks..."
|
||||
self.nodes[0].generate(105)
|
||||
self.sync_all()
|
||||
|
||||
chain_height = self.nodes[1].getblockcount()
|
||||
assert_equal(chain_height, 105)
|
||||
|
||||
print "Testing transaction index..."
|
||||
|
||||
privkey = "cSdkPxkAjA4HDr5VHgsebAPDEh9Gyub4HK8UJr2DFGGqKKy4K5sG"
|
||||
address = "mgY65WSfEmsyYaYPQaXhmXMeBhwp4EcsQW"
|
||||
addressHash = "0b2f0a0c31bfe0406b0ccc1381fdbe311946dadc".decode("hex")
|
||||
scriptPubKey = CScript([OP_DUP, OP_HASH160, addressHash, OP_EQUALVERIFY, OP_CHECKSIG])
|
||||
unspent = self.nodes[0].listunspent()
|
||||
tx = CTransaction()
|
||||
amount = unspent[0]["amount"] * 100000000
|
||||
tx.vin = [CTxIn(COutPoint(int(unspent[0]["txid"], 16), unspent[0]["vout"]))]
|
||||
tx.vout = [CTxOut(amount, scriptPubKey)]
|
||||
tx.rehash()
|
||||
|
||||
signed_tx = self.nodes[0].signrawtransaction(binascii.hexlify(tx.serialize()).decode("utf-8"))
|
||||
txid = self.nodes[0].sendrawtransaction(signed_tx["hex"], True)
|
||||
self.nodes[0].generate(1)
|
||||
self.sync_all()
|
||||
|
||||
# Check verbose raw transaction results
|
||||
verbose = self.nodes[3].getrawtransaction(unspent[0]["txid"], 1)
|
||||
assert_equal(verbose["vout"][0]["valueSat"], 5000000000);
|
||||
assert_equal(verbose["vout"][0]["value"], 50);
|
||||
|
||||
print "Passed\n"
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
TxIndexTest().main()
|
||||
263
qa/zcash/create_benchmark_archive.py
Normal file
263
qa/zcash/create_benchmark_archive.py
Normal file
@@ -0,0 +1,263 @@
|
||||
import binascii
|
||||
import calendar
|
||||
import json
|
||||
import plyvel
|
||||
import progressbar
|
||||
import os
|
||||
import stat
|
||||
import struct
|
||||
import subprocess
|
||||
import sys
|
||||
import tarfile
|
||||
import time
|
||||
|
||||
ZCASH_CLI = './src/zcash-cli'
|
||||
USAGE = """
|
||||
Requirements:
|
||||
- find
|
||||
- xz
|
||||
- %s (edit ZCASH_CLI in this script to alter the path)
|
||||
- A running mainnet zcashd using the default datadir with -txindex=1
|
||||
|
||||
Example usage:
|
||||
|
||||
make -C src/leveldb/
|
||||
virtualenv venv
|
||||
. venv/bin/activate
|
||||
pip install --global-option=build_ext --global-option="-L$(pwd)/src/leveldb/" --global-option="-I$(pwd)/src/leveldb/include/" plyvel
|
||||
pip install progressbar2
|
||||
LD_LIBRARY_PATH=src/leveldb python qa/zcash/create_benchmark_archive.py
|
||||
""" % ZCASH_CLI
|
||||
|
||||
def check_deps():
|
||||
if subprocess.call(['which', 'find', 'xz', ZCASH_CLI], stdout=subprocess.PIPE):
|
||||
print USAGE
|
||||
sys.exit()
|
||||
|
||||
def encode_varint(n):
|
||||
v = bytearray()
|
||||
l = 0
|
||||
while True:
|
||||
v.append((n & 0x7F) | (0x80 if l else 0x00))
|
||||
if (n <= 0x7F):
|
||||
break
|
||||
n = (n >> 7) - 1
|
||||
l += 1
|
||||
return bytes(v)[::-1]
|
||||
|
||||
def decode_varint(v):
|
||||
n = 0
|
||||
for ch in range(len(v)):
|
||||
n = (n << 7) | (ord(v[ch]) & 0x7F)
|
||||
if (ord(v[ch]) & 0x80):
|
||||
n += 1
|
||||
else:
|
||||
return n
|
||||
|
||||
def compress_amount(n):
|
||||
if n == 0:
|
||||
return 0
|
||||
e = 0
|
||||
while (((n % 10) == 0) and e < 9):
|
||||
n /= 10
|
||||
e += 1
|
||||
if e < 9:
|
||||
d = (n % 10)
|
||||
assert(d >= 1 and d <= 9)
|
||||
n /= 10
|
||||
return 1 + (n*9 + d - 1)*10 + e
|
||||
else:
|
||||
return 1 + (n - 1)*10 + 9
|
||||
|
||||
OP_DUP = 0x76
|
||||
OP_EQUAL = 0x87
|
||||
OP_EQUALVERIFY = 0x88
|
||||
OP_HASH160 = 0xa9
|
||||
OP_CHECKSIG = 0xac
|
||||
def to_key_id(script):
|
||||
if len(script) == 25 and \
|
||||
script[0] == OP_DUP and \
|
||||
script[1] == OP_HASH160 and \
|
||||
script[2] == 20 and \
|
||||
script[23] == OP_EQUALVERIFY and \
|
||||
script[24] == OP_CHECKSIG:
|
||||
return script[3:23]
|
||||
return bytes()
|
||||
|
||||
def to_script_id(script):
|
||||
if len(script) == 23 and \
|
||||
script[0] == OP_HASH160 and \
|
||||
script[1] == 20 and \
|
||||
script[22] == OP_EQUAL:
|
||||
return script[2:22]
|
||||
return bytes()
|
||||
|
||||
def to_pubkey(script):
|
||||
if len(script) == 35 and \
|
||||
script[0] == 33 and \
|
||||
script[34] == OP_CHECKSIG and \
|
||||
(script[1] == 0x02 or script[1] == 0x03):
|
||||
return script[1:34]
|
||||
if len(script) == 67 and \
|
||||
script[0] == 65 and \
|
||||
script[66] == OP_CHECKSIG and \
|
||||
script[1] == 0x04:
|
||||
return script[1:66] # assuming is fully valid
|
||||
return bytes()
|
||||
|
||||
def compress_script(script):
|
||||
result = bytearray()
|
||||
|
||||
key_id = to_key_id(script)
|
||||
if key_id:
|
||||
result.append(0x00)
|
||||
result.extend(key_id)
|
||||
return bytes(result)
|
||||
|
||||
script_id = to_script_id(script)
|
||||
if script_id:
|
||||
result.append(0x01)
|
||||
result.extend(script_id)
|
||||
return bytes(result)
|
||||
|
||||
pubkey = to_pubkey(script)
|
||||
if pubkey:
|
||||
result.append(0x00)
|
||||
result.extend(pubkey[1:33])
|
||||
if pubkey[0] == 0x02 or pubkey[0] == 0x03:
|
||||
result[0] = pubkey[0]
|
||||
return bytes(result)
|
||||
elif pubkey[0] == 0x04:
|
||||
result[0] = 0x04 | (pubkey[64] & 0x01)
|
||||
return bytes(result)
|
||||
|
||||
size = len(script) + 6
|
||||
result.append(encode_varint(size))
|
||||
result.extend(script)
|
||||
return bytes(result)
|
||||
|
||||
def deterministic_filter(tarinfo):
|
||||
tarinfo.uid = tarinfo.gid = 0
|
||||
tarinfo.uname = tarinfo.gname = "root"
|
||||
tarinfo.mtime = calendar.timegm(time.strptime('2017-05-17', '%Y-%m-%d'))
|
||||
tarinfo.mode |= stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP
|
||||
tarinfo.mode &= ~stat.S_IWGRP
|
||||
if tarinfo.isdir():
|
||||
tarinfo.mode |= \
|
||||
stat.S_IXUSR | \
|
||||
stat.S_IXGRP | \
|
||||
stat.S_IXOTH
|
||||
else:
|
||||
tarinfo.mode &= \
|
||||
~stat.S_IXUSR & \
|
||||
~stat.S_IXGRP & \
|
||||
~stat.S_IXOTH
|
||||
return tarinfo
|
||||
|
||||
def create_benchmark_archive(blk_hash):
|
||||
blk = json.loads(subprocess.check_output([ZCASH_CLI, 'getblock', blk_hash]))
|
||||
print 'Height: %d' % blk['height']
|
||||
print 'Transactions: %d' % len(blk['tx'])
|
||||
|
||||
os.mkdir('benchmark')
|
||||
with open('benchmark/block-%d.dat' % blk['height'], 'wb') as f:
|
||||
f.write(binascii.unhexlify(subprocess.check_output([ZCASH_CLI, 'getblock', blk_hash, 'false']).strip()))
|
||||
|
||||
txs = [json.loads(subprocess.check_output([ZCASH_CLI, 'getrawtransaction', tx, '1'])
|
||||
) for tx in blk['tx']]
|
||||
|
||||
js_txs = len([tx for tx in txs if len(tx['vjoinsplit']) > 0])
|
||||
if js_txs:
|
||||
print 'Block contains %d JoinSplit-containing transactions' % js_txs
|
||||
return
|
||||
|
||||
inputs = [(x['txid'], x['vout']) for tx in txs for x in tx['vin'] if x.has_key('txid')]
|
||||
print 'Total inputs: %d' % len(inputs)
|
||||
|
||||
unique_inputs = {}
|
||||
for i in sorted(inputs):
|
||||
if unique_inputs.has_key(i[0]):
|
||||
unique_inputs[i[0]].append(i[1])
|
||||
else:
|
||||
unique_inputs[i[0]] = [i[1]]
|
||||
print 'Unique input transactions: %d' % len(unique_inputs)
|
||||
|
||||
db_path = 'benchmark/block-%d-inputs' % blk['height']
|
||||
db = plyvel.DB(db_path, create_if_missing=True)
|
||||
wb = db.write_batch()
|
||||
bar = progressbar.ProgressBar(redirect_stdout=True)
|
||||
print 'Collecting input coins for block'
|
||||
for tx in bar(unique_inputs.keys()):
|
||||
rawtx = json.loads(subprocess.check_output([ZCASH_CLI, 'getrawtransaction', tx, '1']))
|
||||
|
||||
mask_size = 0
|
||||
mask_code = 0
|
||||
b = 0
|
||||
while 2+b*8 < len(rawtx['vout']):
|
||||
zero = True
|
||||
i = 0
|
||||
while i < 8 and 2+b*8+i < len(rawtx['vout']):
|
||||
if 2+b*8+i in unique_inputs[tx]:
|
||||
zero = False
|
||||
i += 1
|
||||
if not zero:
|
||||
mask_size = b + 1
|
||||
mask_code += 1
|
||||
b += 1
|
||||
|
||||
coinbase = len(rawtx['vin']) == 1 and 'coinbase' in rawtx['vin'][0]
|
||||
first = len(rawtx['vout']) > 0 and 0 in unique_inputs[tx]
|
||||
second = len(rawtx['vout']) > 1 and 1 in unique_inputs[tx]
|
||||
code = 8*(mask_code - (0 if first or second else 1)) + \
|
||||
(1 if coinbase else 0) + \
|
||||
(2 if first else 0) + \
|
||||
(4 if second else 0)
|
||||
|
||||
coins = bytearray()
|
||||
# Serialized format:
|
||||
# - VARINT(nVersion)
|
||||
coins.extend(encode_varint(rawtx['version']))
|
||||
# - VARINT(nCode)
|
||||
coins.extend(encode_varint(code))
|
||||
# - unspentness bitvector, for vout[2] and further; least significant byte first
|
||||
for b in range(mask_size):
|
||||
avail = 0
|
||||
i = 0
|
||||
while i < 8 and 2+b*8+i < len(rawtx['vout']):
|
||||
if 2+b*8+i in unique_inputs[tx]:
|
||||
avail |= (1 << i)
|
||||
i += 1
|
||||
coins.append(avail)
|
||||
# - the non-spent CTxOuts (via CTxOutCompressor)
|
||||
for i in range(len(rawtx['vout'])):
|
||||
if i in unique_inputs[tx]:
|
||||
coins.extend(encode_varint(compress_amount(int(rawtx['vout'][i]['valueZat']))))
|
||||
coins.extend(compress_script(
|
||||
binascii.unhexlify(rawtx['vout'][i]['scriptPubKey']['hex'])))
|
||||
# - VARINT(nHeight)
|
||||
coins.extend(encode_varint(json.loads(
|
||||
subprocess.check_output([ZCASH_CLI, 'getblockheader', rawtx['blockhash']])
|
||||
)['height']))
|
||||
|
||||
db_key = b'c' + bytes(binascii.unhexlify(tx)[::-1])
|
||||
db_val = bytes(coins)
|
||||
wb.put(db_key, db_val)
|
||||
|
||||
wb.write()
|
||||
db.close()
|
||||
|
||||
# Make reproducible archive
|
||||
os.remove('%s/LOG' % db_path)
|
||||
files = subprocess.check_output(['find', 'benchmark']).strip().split('\n')
|
||||
archive_name = 'block-%d.tar' % blk['height']
|
||||
tar = tarfile.open(archive_name, 'w')
|
||||
for name in sorted(files):
|
||||
tar.add(name, recursive=False, filter=deterministic_filter)
|
||||
tar.close()
|
||||
subprocess.check_call(['xz', '-6', archive_name])
|
||||
print 'Created archive %s.xz' % archive_name
|
||||
subprocess.call(['rm', '-r', 'benchmark'])
|
||||
|
||||
if __name__ == '__main__':
|
||||
check_deps()
|
||||
create_benchmark_archive('0000000007cdb809e48e51dd0b530e8f5073e0a9e9bd7ae920fe23e874658c74')
|
||||
60
qa/zcash/create_wallet_200k_utxos.py
Normal file
60
qa/zcash/create_wallet_200k_utxos.py
Normal file
@@ -0,0 +1,60 @@
|
||||
#!/usr/bin/env python2
|
||||
# Copyright (c) 2017 The Zcash developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#
|
||||
# Create a large wallet
|
||||
#
|
||||
# To use:
|
||||
# - Copy to qa/rpc-tests/wallet_large.py
|
||||
# - Add wallet_large.py to RPC tests list
|
||||
# - ./qa/pull-tester/rpc-tests.sh wallet_large --nocleanup
|
||||
# - Archive the resulting /tmp/test###### directory
|
||||
#
|
||||
|
||||
from test_framework.test_framework import BitcoinTestFramework
|
||||
from test_framework.util import (
|
||||
assert_equal,
|
||||
connect_nodes_bi,
|
||||
initialize_chain_clean,
|
||||
start_nodes,
|
||||
)
|
||||
|
||||
from decimal import Decimal
|
||||
|
||||
|
||||
class LargeWalletTest(BitcoinTestFramework):
|
||||
|
||||
def setup_chain(self):
|
||||
print("Initializing test directory "+self.options.tmpdir)
|
||||
initialize_chain_clean(self.options.tmpdir, 2)
|
||||
|
||||
def setup_network(self):
|
||||
self.nodes = start_nodes(2, self.options.tmpdir)
|
||||
connect_nodes_bi(self.nodes, 0, 1)
|
||||
self.is_network_split = False
|
||||
self.sync_all()
|
||||
|
||||
def run_test(self):
|
||||
self.nodes[1].generate(103)
|
||||
self.sync_all()
|
||||
|
||||
inputs = []
|
||||
for i in range(200000):
|
||||
taddr = self.nodes[0].getnewaddress()
|
||||
inputs.append(self.nodes[1].sendtoaddress(taddr, Decimal("0.001")))
|
||||
if i % 1000 == 0:
|
||||
self.nodes[1].generate(1)
|
||||
self.sync_all()
|
||||
|
||||
self.nodes[1].generate(1)
|
||||
self.sync_all()
|
||||
print('Node 0: %d transactions, %d UTXOs' %
|
||||
(len(self.nodes[0].listtransactions()), len(self.nodes[0].listunspent())))
|
||||
print('Node 1: %d transactions, %d UTXOs' %
|
||||
(len(self.nodes[1].listtransactions()), len(self.nodes[1].listunspent())))
|
||||
assert_equal(len(self.nodes[0].listunspent()), len(inputs))
|
||||
|
||||
if __name__ == '__main__':
|
||||
LargeWalletTest().main()
|
||||
@@ -1,47 +1,201 @@
|
||||
#!/bin/bash
|
||||
#!/usr/bin/env python2
|
||||
#
|
||||
# Execute all of the automated tests related to Zcash.
|
||||
#
|
||||
|
||||
set -eu
|
||||
import argparse
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
SUITE_EXIT_STATUS=0
|
||||
REPOROOT="$(readlink -f "$(dirname "$0")"/../../)"
|
||||
REPOROOT = os.path.dirname(
|
||||
os.path.dirname(
|
||||
os.path.dirname(
|
||||
os.path.abspath(__file__)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
function run_test_phase
|
||||
{
|
||||
echo "===== BEGIN: $*"
|
||||
set +e
|
||||
eval "$@"
|
||||
if [ $? -eq 0 ]
|
||||
then
|
||||
echo "===== PASSED: $*"
|
||||
else
|
||||
echo "===== FAILED: $*"
|
||||
SUITE_EXIT_STATUS=1
|
||||
fi
|
||||
set -e
|
||||
def repofile(filename):
|
||||
return os.path.join(REPOROOT, filename)
|
||||
|
||||
|
||||
#
|
||||
# Custom test runners
|
||||
#
|
||||
|
||||
RE_RPATH_RUNPATH = re.compile('No RPATH.*No RUNPATH')
|
||||
RE_FORTIFY_AVAILABLE = re.compile('FORTIFY_SOURCE support available.*Yes')
|
||||
RE_FORTIFY_USED = re.compile('Binary compiled with FORTIFY_SOURCE support.*Yes')
|
||||
|
||||
def test_rpath_runpath(filename):
|
||||
output = subprocess.check_output(
|
||||
[repofile('qa/zcash/checksec.sh'), '--file', repofile(filename)]
|
||||
)
|
||||
if RE_RPATH_RUNPATH.search(output):
|
||||
print('PASS: %s has no RPATH or RUNPATH.' % filename)
|
||||
return True
|
||||
else:
|
||||
print('FAIL: %s has an RPATH or a RUNPATH.' % filename)
|
||||
print(output)
|
||||
return False
|
||||
|
||||
def test_fortify_source(filename):
|
||||
proc = subprocess.Popen(
|
||||
[repofile('qa/zcash/checksec.sh'), '--fortify-file', repofile(filename)],
|
||||
stdout=subprocess.PIPE,
|
||||
)
|
||||
line1 = proc.stdout.readline()
|
||||
line2 = proc.stdout.readline()
|
||||
proc.terminate()
|
||||
if RE_FORTIFY_AVAILABLE.search(line1) and RE_FORTIFY_USED.search(line2):
|
||||
print('PASS: %s has FORTIFY_SOURCE.' % filename)
|
||||
return True
|
||||
else:
|
||||
print('FAIL: %s is missing FORTIFY_SOURCE.' % filename)
|
||||
return False
|
||||
|
||||
def check_security_hardening():
|
||||
ret = True
|
||||
|
||||
# PIE, RELRO, Canary, and NX are tested by make check-security.
|
||||
ret &= subprocess.call(['make', '-C', repofile('src'), 'check-security']) == 0
|
||||
|
||||
ret &= test_rpath_runpath('src/zcashd')
|
||||
ret &= test_rpath_runpath('src/zcash-cli')
|
||||
ret &= test_rpath_runpath('src/zcash-gtest')
|
||||
ret &= test_rpath_runpath('src/zcash-tx')
|
||||
ret &= test_rpath_runpath('src/test/test_bitcoin')
|
||||
ret &= test_rpath_runpath('src/zcash/GenerateParams')
|
||||
|
||||
# NOTE: checksec.sh does not reliably determine whether FORTIFY_SOURCE
|
||||
# is enabled for the entire binary. See issue #915.
|
||||
ret &= test_fortify_source('src/zcashd')
|
||||
ret &= test_fortify_source('src/zcash-cli')
|
||||
ret &= test_fortify_source('src/zcash-gtest')
|
||||
ret &= test_fortify_source('src/zcash-tx')
|
||||
ret &= test_fortify_source('src/test/test_bitcoin')
|
||||
ret &= test_fortify_source('src/zcash/GenerateParams')
|
||||
|
||||
return ret
|
||||
|
||||
def ensure_no_dot_so_in_depends():
|
||||
arch_dir = os.path.join(
|
||||
REPOROOT,
|
||||
'depends',
|
||||
'x86_64-unknown-linux-gnu',
|
||||
)
|
||||
|
||||
exit_code = 0
|
||||
|
||||
if os.path.isdir(arch_dir):
|
||||
lib_dir = os.path.join(arch_dir, 'lib')
|
||||
libraries = os.listdir(lib_dir)
|
||||
|
||||
for lib in libraries:
|
||||
if lib.find(".so") != -1:
|
||||
print lib
|
||||
exit_code = 1
|
||||
else:
|
||||
exit_code = 2
|
||||
print "arch-specific build dir not present: {}".format(arch_dir)
|
||||
print "Did you build the ./depends tree?"
|
||||
print "Are you on a currently unsupported architecture?"
|
||||
|
||||
if exit_code == 0:
|
||||
print "PASS."
|
||||
else:
|
||||
print "FAIL."
|
||||
|
||||
return exit_code == 0
|
||||
|
||||
def util_test():
|
||||
return subprocess.call(
|
||||
[repofile('src/test/bitcoin-util-test.py')],
|
||||
cwd=repofile('src'),
|
||||
env={'PYTHONPATH': repofile('src/test'), 'srcdir': repofile('src')}
|
||||
) == 0
|
||||
|
||||
|
||||
#
|
||||
# Tests
|
||||
#
|
||||
|
||||
STAGES = [
|
||||
'btest',
|
||||
'gtest',
|
||||
'sec-hard',
|
||||
'no-dot-so',
|
||||
'util-test',
|
||||
'secp256k1',
|
||||
'libsnark',
|
||||
'univalue',
|
||||
'rpc',
|
||||
]
|
||||
|
||||
STAGE_COMMANDS = {
|
||||
'btest': [repofile('src/test/test_bitcoin'), '-p'],
|
||||
'gtest': [repofile('src/zcash-gtest')],
|
||||
'sec-hard': check_security_hardening,
|
||||
'no-dot-so': ensure_no_dot_so_in_depends,
|
||||
'util-test': util_test,
|
||||
'secp256k1': ['make', '-C', repofile('src/secp256k1'), 'check'],
|
||||
'libsnark': ['make', '-C', repofile('src'), 'libsnark-tests'],
|
||||
'univalue': ['make', '-C', repofile('src/univalue'), 'check'],
|
||||
'rpc': [repofile('qa/pull-tester/rpc-tests.sh')],
|
||||
}
|
||||
|
||||
cd "${REPOROOT}"
|
||||
|
||||
# Test phases:
|
||||
run_test_phase "${REPOROOT}/qa/zcash/check-security-hardening.sh"
|
||||
run_test_phase "${REPOROOT}/qa/zcash/ensure-no-dot-so-in-depends.py"
|
||||
#
|
||||
# Test driver
|
||||
#
|
||||
|
||||
# If make check fails, show test-suite.log as part of our run_test_phase
|
||||
# output (and fail the phase with false):
|
||||
run_test_phase make check '||' \
|
||||
'{' \
|
||||
echo '=== ./src/test-suite.log ===' ';' \
|
||||
cat './src/test-suite.log' ';' \
|
||||
false ';' \
|
||||
'}'
|
||||
def run_stage(stage):
|
||||
print('Running stage %s' % stage)
|
||||
print('=' * (len(stage) + 14))
|
||||
print
|
||||
|
||||
exit $SUITE_EXIT_STATUS
|
||||
cmd = STAGE_COMMANDS[stage]
|
||||
if type(cmd) == type([]):
|
||||
ret = subprocess.call(cmd) == 0
|
||||
else:
|
||||
ret = cmd()
|
||||
|
||||
print
|
||||
print('-' * (len(stage) + 15))
|
||||
print('Finished stage %s' % stage)
|
||||
print
|
||||
|
||||
return ret
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('--list-stages', dest='list', action='store_true')
|
||||
parser.add_argument('stage', nargs='*', default=STAGES,
|
||||
help='One of %s'%STAGES)
|
||||
args = parser.parse_args()
|
||||
|
||||
# Check for list
|
||||
if args.list:
|
||||
for s in STAGES:
|
||||
print(s)
|
||||
sys.exit(0)
|
||||
|
||||
# Check validity of stages
|
||||
for s in args.stage:
|
||||
if s not in STAGES:
|
||||
print("Invalid stage '%s' (choose from %s)" % (s, STAGES))
|
||||
sys.exit(1)
|
||||
|
||||
# Run the stages
|
||||
passed = True
|
||||
for s in args.stage:
|
||||
passed &= run_stage(s)
|
||||
|
||||
if not passed:
|
||||
print("!!! One or more test stages failed !!!")
|
||||
sys.exit(1)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -1,37 +1,113 @@
|
||||
#!/bin/bash
|
||||
set -u
|
||||
|
||||
set -e
|
||||
|
||||
DATADIR=./benchmark-datadir
|
||||
SHA256CMD="$(command -v sha256sum || echo shasum)"
|
||||
SHA256ARGS="$(command -v sha256sum >/dev/null || echo '-a 256')"
|
||||
|
||||
function zcash_rpc {
|
||||
./src/zcash-cli -datadir="$DATADIR" -rpcwait -rpcuser=user -rpcpassword=password -rpcport=5983 "$@"
|
||||
./src/zcash-cli -datadir="$DATADIR" -rpcuser=user -rpcpassword=password -rpcport=5983 "$@"
|
||||
}
|
||||
|
||||
function zcash_rpc_slow {
|
||||
# Timeout of 1 hour
|
||||
zcash_rpc -rpcclienttimeout=3600 "$@"
|
||||
}
|
||||
|
||||
function zcash_rpc_veryslow {
|
||||
# Timeout of 2.5 hours
|
||||
zcash_rpc -rpcclienttimeout=9000 "$@"
|
||||
}
|
||||
|
||||
function zcash_rpc_wait_for_start {
|
||||
zcash_rpc -rpcwait getinfo > /dev/null
|
||||
}
|
||||
|
||||
function zcashd_generate {
|
||||
zcash_rpc generate 101 > /dev/null
|
||||
}
|
||||
|
||||
function extract_benchmark_datadir {
|
||||
if [ -f "$1.tar.xz" ]; then
|
||||
# Check the hash of the archive:
|
||||
"$SHA256CMD" $SHA256ARGS -c <<EOF
|
||||
$2 $1.tar.xz
|
||||
EOF
|
||||
ARCHIVE_RESULT=$?
|
||||
else
|
||||
echo "$1.tar.xz not found."
|
||||
ARCHIVE_RESULT=1
|
||||
fi
|
||||
if [ $ARCHIVE_RESULT -ne 0 ]; then
|
||||
zcashd_stop
|
||||
echo
|
||||
echo "Please download it and place it in the base directory of the repository."
|
||||
exit 1
|
||||
fi
|
||||
xzcat "$1.tar.xz" | tar x
|
||||
}
|
||||
|
||||
function use_200k_benchmark {
|
||||
rm -rf benchmark-200k-UTXOs
|
||||
extract_benchmark_datadir benchmark-200k-UTXOs dc8ab89eaa13730da57d9ac373c1f4e818a37181c1443f61fd11327e49fbcc5e
|
||||
DATADIR="./benchmark-200k-UTXOs/node$1"
|
||||
}
|
||||
|
||||
function zcashd_start {
|
||||
rm -rf "$DATADIR"
|
||||
mkdir -p "$DATADIR"
|
||||
touch "$DATADIR/zcash.conf"
|
||||
case "$1" in
|
||||
sendtoaddress|loadwallet|listunspent)
|
||||
case "$2" in
|
||||
200k-recv)
|
||||
use_200k_benchmark 0
|
||||
;;
|
||||
200k-send)
|
||||
use_200k_benchmark 1
|
||||
;;
|
||||
*)
|
||||
echo "Bad arguments to zcashd_start."
|
||||
exit 1
|
||||
esac
|
||||
;;
|
||||
*)
|
||||
rm -rf "$DATADIR"
|
||||
mkdir -p "$DATADIR/regtest"
|
||||
touch "$DATADIR/zcash.conf"
|
||||
esac
|
||||
./src/zcashd -regtest -datadir="$DATADIR" -rpcuser=user -rpcpassword=password -rpcport=5983 -showmetrics=0 &
|
||||
ZCASHD_PID=$!
|
||||
zcash_rpc_wait_for_start
|
||||
}
|
||||
|
||||
function zcashd_stop {
|
||||
zcash_rpc stop > /dev/null
|
||||
wait $ZCASH_PID
|
||||
wait $ZCASHD_PID
|
||||
}
|
||||
|
||||
function zcashd_massif_start {
|
||||
rm -rf "$DATADIR"
|
||||
mkdir -p "$DATADIR"
|
||||
touch "$DATADIR/zcash.conf"
|
||||
case "$1" in
|
||||
sendtoaddress|loadwallet|listunspent)
|
||||
case "$2" in
|
||||
200k-recv)
|
||||
use_200k_benchmark 0
|
||||
;;
|
||||
200k-send)
|
||||
use_200k_benchmark 1
|
||||
;;
|
||||
*)
|
||||
echo "Bad arguments to zcashd_massif_start."
|
||||
exit 1
|
||||
esac
|
||||
;;
|
||||
*)
|
||||
rm -rf "$DATADIR"
|
||||
mkdir -p "$DATADIR/regtest"
|
||||
touch "$DATADIR/zcash.conf"
|
||||
esac
|
||||
rm -f massif.out
|
||||
valgrind --tool=massif --time-unit=ms --massif-out-file=massif.out ./src/zcashd -regtest -datadir="$DATADIR" -rpcuser=user -rpcpassword=password -rpcport=5983 -showmetrics=0 &
|
||||
ZCASHD_PID=$!
|
||||
zcash_rpc_wait_for_start
|
||||
}
|
||||
|
||||
function zcashd_massif_stop {
|
||||
@@ -42,11 +118,12 @@ function zcashd_massif_stop {
|
||||
|
||||
function zcashd_valgrind_start {
|
||||
rm -rf "$DATADIR"
|
||||
mkdir -p "$DATADIR"
|
||||
mkdir -p "$DATADIR/regtest"
|
||||
touch "$DATADIR/zcash.conf"
|
||||
rm -f valgrind.out
|
||||
valgrind --leak-check=yes -v --error-limit=no --log-file="valgrind.out" ./src/zcashd -regtest -datadir="$DATADIR" -rpcuser=user -rpcpassword=password -rpcport=5983 -showmetrics=0 &
|
||||
ZCASHD_PID=$!
|
||||
zcash_rpc_wait_for_start
|
||||
}
|
||||
|
||||
function zcashd_valgrind_stop {
|
||||
@@ -55,12 +132,41 @@ function zcashd_valgrind_stop {
|
||||
cat valgrind.out
|
||||
}
|
||||
|
||||
function extract_benchmark_data {
|
||||
if [ -f "block-107134.tar.xz" ]; then
|
||||
# Check the hash of the archive:
|
||||
"$SHA256CMD" $SHA256ARGS -c <<EOF
|
||||
4bd5ad1149714394e8895fa536725ed5d6c32c99812b962bfa73f03b5ffad4bb block-107134.tar.xz
|
||||
EOF
|
||||
ARCHIVE_RESULT=$?
|
||||
else
|
||||
echo "block-107134.tar.xz not found."
|
||||
ARCHIVE_RESULT=1
|
||||
fi
|
||||
if [ $ARCHIVE_RESULT -ne 0 ]; then
|
||||
zcashd_stop
|
||||
echo
|
||||
echo "Please generate it using qa/zcash/create_benchmark_archive.py"
|
||||
echo "and place it in the base directory of the repository."
|
||||
echo "Usage details are inside the Python script."
|
||||
exit 1
|
||||
fi
|
||||
xzcat block-107134.tar.xz | tar x -C "$DATADIR/regtest"
|
||||
}
|
||||
|
||||
|
||||
if [ $# -lt 2 ]
|
||||
then
|
||||
echo "$0 : At least two arguments are required!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Precomputation
|
||||
case "$1" in
|
||||
*)
|
||||
case "$2" in
|
||||
verifyjoinsplit)
|
||||
zcashd_start
|
||||
zcashd_start "${@:2}"
|
||||
RAWJOINSPLIT=$(zcash_rpc zcsamplejoinsplit)
|
||||
zcashd_stop
|
||||
esac
|
||||
@@ -68,7 +174,7 @@ esac
|
||||
|
||||
case "$1" in
|
||||
time)
|
||||
zcashd_start
|
||||
zcashd_start "${@:2}"
|
||||
case "$2" in
|
||||
sleep)
|
||||
zcash_rpc zcbenchmark sleep 10
|
||||
@@ -83,7 +189,7 @@ case "$1" in
|
||||
zcash_rpc zcbenchmark verifyjoinsplit 1000 "\"$RAWJOINSPLIT\""
|
||||
;;
|
||||
solveequihash)
|
||||
zcash_rpc zcbenchmark solveequihash 50 "${@:3}"
|
||||
zcash_rpc_slow zcbenchmark solveequihash 50 "${@:3}"
|
||||
;;
|
||||
verifyequihash)
|
||||
zcash_rpc zcbenchmark verifyequihash 1000
|
||||
@@ -97,15 +203,28 @@ case "$1" in
|
||||
incnotewitnesses)
|
||||
zcash_rpc zcbenchmark incnotewitnesses 100 "${@:3}"
|
||||
;;
|
||||
connectblockslow)
|
||||
extract_benchmark_data
|
||||
zcash_rpc zcbenchmark connectblockslow 10
|
||||
;;
|
||||
sendtoaddress)
|
||||
zcash_rpc zcbenchmark sendtoaddress 10 "${@:4}"
|
||||
;;
|
||||
loadwallet)
|
||||
zcash_rpc zcbenchmark loadwallet 10
|
||||
;;
|
||||
listunspent)
|
||||
zcash_rpc zcbenchmark listunspent 10
|
||||
;;
|
||||
*)
|
||||
zcashd_stop
|
||||
echo "Bad arguments."
|
||||
echo "Bad arguments to time."
|
||||
exit 1
|
||||
esac
|
||||
zcashd_stop
|
||||
;;
|
||||
memory)
|
||||
zcashd_massif_start
|
||||
zcashd_massif_start "${@:2}"
|
||||
case "$2" in
|
||||
sleep)
|
||||
zcash_rpc zcbenchmark sleep 1
|
||||
@@ -114,26 +233,42 @@ case "$1" in
|
||||
zcash_rpc zcbenchmark parameterloading 1
|
||||
;;
|
||||
createjoinsplit)
|
||||
zcash_rpc zcbenchmark createjoinsplit 1 "${@:3}"
|
||||
zcash_rpc_slow zcbenchmark createjoinsplit 1 "${@:3}"
|
||||
;;
|
||||
verifyjoinsplit)
|
||||
zcash_rpc zcbenchmark verifyjoinsplit 1 "\"$RAWJOINSPLIT\""
|
||||
;;
|
||||
solveequihash)
|
||||
zcash_rpc zcbenchmark solveequihash 1 "${@:3}"
|
||||
zcash_rpc_slow zcbenchmark solveequihash 1 "${@:3}"
|
||||
;;
|
||||
verifyequihash)
|
||||
zcash_rpc zcbenchmark verifyequihash 1
|
||||
;;
|
||||
validatelargetx)
|
||||
zcash_rpc zcbenchmark validatelargetx 1
|
||||
;;
|
||||
trydecryptnotes)
|
||||
zcash_rpc zcbenchmark trydecryptnotes 1 "${@:3}"
|
||||
;;
|
||||
incnotewitnesses)
|
||||
zcash_rpc zcbenchmark incnotewitnesses 1 "${@:3}"
|
||||
;;
|
||||
connectblockslow)
|
||||
extract_benchmark_data
|
||||
zcash_rpc zcbenchmark connectblockslow 1
|
||||
;;
|
||||
sendtoaddress)
|
||||
zcash_rpc zcbenchmark sendtoaddress 1 "${@:4}"
|
||||
;;
|
||||
loadwallet)
|
||||
# The initial load is sufficient for measurement
|
||||
;;
|
||||
listunspent)
|
||||
zcash_rpc zcbenchmark listunspent 1
|
||||
;;
|
||||
*)
|
||||
zcashd_massif_stop
|
||||
echo "Bad arguments."
|
||||
echo "Bad arguments to memory."
|
||||
exit 1
|
||||
esac
|
||||
zcashd_massif_stop
|
||||
@@ -149,13 +284,13 @@ case "$1" in
|
||||
zcash_rpc zcbenchmark parameterloading 1
|
||||
;;
|
||||
createjoinsplit)
|
||||
zcash_rpc zcbenchmark createjoinsplit 1 "${@:3}"
|
||||
zcash_rpc_veryslow zcbenchmark createjoinsplit 1 "${@:3}"
|
||||
;;
|
||||
verifyjoinsplit)
|
||||
zcash_rpc zcbenchmark verifyjoinsplit 1 "\"$RAWJOINSPLIT\""
|
||||
;;
|
||||
solveequihash)
|
||||
zcash_rpc zcbenchmark solveequihash 1 "${@:3}"
|
||||
zcash_rpc_veryslow zcbenchmark solveequihash 1 "${@:3}"
|
||||
;;
|
||||
verifyequihash)
|
||||
zcash_rpc zcbenchmark verifyequihash 1
|
||||
@@ -166,9 +301,13 @@ case "$1" in
|
||||
incnotewitnesses)
|
||||
zcash_rpc zcbenchmark incnotewitnesses 1 "${@:3}"
|
||||
;;
|
||||
connectblockslow)
|
||||
extract_benchmark_data
|
||||
zcash_rpc zcbenchmark connectblockslow 1
|
||||
;;
|
||||
*)
|
||||
zcashd_valgrind_stop
|
||||
echo "Bad arguments."
|
||||
echo "Bad arguments to valgrind."
|
||||
exit 1
|
||||
esac
|
||||
zcashd_valgrind_stop
|
||||
@@ -189,14 +328,14 @@ case "$1" in
|
||||
rm -f valgrind.out
|
||||
;;
|
||||
*)
|
||||
echo "Bad arguments."
|
||||
echo "Bad arguments to valgrind-tests."
|
||||
exit 1
|
||||
esac
|
||||
;;
|
||||
*)
|
||||
echo "Bad arguments."
|
||||
echo "Invalid benchmark type."
|
||||
exit 1
|
||||
esac
|
||||
|
||||
# Cleanup
|
||||
rm -rf "$DATADIR"
|
||||
rm -rf "$DATADIR"
|
||||
@@ -40,4 +40,4 @@ for filename in get_depends_sources_list():
|
||||
sys.exit(1)
|
||||
|
||||
print "PASS."
|
||||
sys.exit(0)
|
||||
sys.exit(0)
|
||||
Reference in New Issue
Block a user