FireMartZ
6 years ago
121 changed files with 5336 additions and 115 deletions
@ -1 +1 @@ |
|||||
# mainnet nodes |
# mainnet nodes |
@ -1,2 +1,3 @@ |
|||||
# List of fixed seed nodes for testnet |
# List of fixed seed nodes for testnet |
||||
|
|
||||
|
|
||||
|
@ -1 +1,2 @@ |
|||||
dist_man1_MANS=hushd.1 hush-cli.1 hush-fetch-params.1 hush-tx.1 |
dist_man1_MANS=hushd.1 hush-cli.1 hush-fetch-params.1 hush-tx.1 |
||||
|
|
||||
|
@ -0,0 +1,88 @@ |
|||||
|
Changelog |
||||
|
========= |
||||
|
|
||||
|
Ariel Gabizon (1): |
||||
|
boost::format -> tinyformat |
||||
|
|
||||
|
Bruno Arueira (1): |
||||
|
Removes out bitcoin mention in favor for zcash |
||||
|
|
||||
|
Cory Fields (1): |
||||
|
httpserver: explicitly detach worker threads |
||||
|
|
||||
|
Duke Leto (1): |
||||
|
Update performance-measurements.sh |
||||
|
|
||||
|
Jack Grigg (36): |
||||
|
Squashed 'src/snark/' content from commit 9ada3f8 |
||||
|
Add libsnark compile flag to not copy DEPINST to PREFIX |
||||
|
Add Ansible playbook for grind workers |
||||
|
Add connections in BIP65 and BIP66 tests to the test manager |
||||
|
Add benchmark for listunspent |
||||
|
[Test] MiniNode: Implement JSDescription parsing |
||||
|
[Test] MiniNode: Implement v2 CTransaction parsing |
||||
|
[Test] MiniNode: Implement Zcash block parsing |
||||
|
[Test] MiniNode: Update protocol version and network magics |
||||
|
[Test] MiniNode: Use Zcash PoW |
||||
|
[Test] MiniNode: Fix coinbase creation |
||||
|
[Test] MiniNode: Coerce OP_PUSHDATA bytearrays to bytes |
||||
|
[Test] MiniNode: Implement Zcash coinbase |
||||
|
Fix BIP65 and BIP66 tests |
||||
|
Un-indent RPC test output in test runner |
||||
|
Replace full-test-suite.sh with a new test suite driver script |
||||
|
Move ensure-no-dot-so-in-depends.py into full_test_suite.py |
||||
|
Move check-security-hardening.sh into full_test_suite.py |
||||
|
Add memory benchmark for validatelargetx |
||||
|
Migrate libsnark test code to Google Test |
||||
|
Remove test code corresponding to removed code |
||||
|
Add alt_bn128 to QAP and Merkle tree gadget tests |
||||
|
Update libsnark LDLIBS |
||||
|
Add "make check" to libsnark that runs the Google Tests |
||||
|
Add "make libsnark-tests" that runs libsnark's "make check" |
||||
|
Changes to get test_r1cs_ppzksnark passing |
||||
|
Add bitcoin-util-test.py to full_test_suite.py |
||||
|
Add stdout notice if any stage fails |
||||
|
Add libsnark to "make clean" |
||||
|
Ensure that libsnark is built first, so its headers are available |
||||
|
Remove OpenSSL libraries from libsnark LDLIBS |
||||
|
Add libsnark tests to full_test_suite.py |
||||
|
Add --list-stages argument to full_test_suite.py |
||||
|
Fix NPE in rpc_wallet_tests |
||||
|
make-release.py: Versioning changes for 1.0.13-rc1. |
||||
|
make-release.py: Updated manpages for 1.0.13-rc1. |
||||
|
Change auto-senescence cycle to 16 weeks |
||||
|
|
||||
|
Jason Davies (1): |
||||
|
Replace "bitcoin" with "Zcash". |
||||
|
|
||||
|
Jay Graber (1): |
||||
|
s/zcash/Zcash |
||||
|
|
||||
|
Jonathan "Duke" Leto (1): |
||||
|
Fix bug where performance-measurements.sh fails hards when given no args |
||||
|
|
||||
|
João Barbosa (1): |
||||
|
Improve shutdown process |
||||
|
|
||||
|
Sean Bowe (5): |
||||
|
Remove libsnark from depends system and integrate it into build system. |
||||
|
Remove crusty old "loadVerifyingKey"/"loadProvingKey" APIs and associated invariants. |
||||
|
Refactor proof generation function. |
||||
|
Add streaming prover. |
||||
|
Integrate low memory prover. |
||||
|
|
||||
|
Simon Liu (7): |
||||
|
Replace 'bitcoin address' with 'zcash address'. |
||||
|
Closes #2639. z_shieldcoinbase is now supported, no longer experimental. |
||||
|
Closes #2263 fixing broken pipe error. |
||||
|
Closes #2576. Update link to security info on z.cash website. |
||||
|
Closes #2639. Adds optional limit parameter with a default value of 50. |
||||
|
Fix an issue where qa test wallet_shieldcoinbase could hang. |
||||
|
Add payment disclosure as experimental feature. |
||||
|
|
||||
|
Wladimir J. van der Laan (4): |
||||
|
Make HTTP server shutdown more graceful |
||||
|
http: Wait for worker threads to exit |
||||
|
http: Force-exit event loop after predefined time |
||||
|
http: speed up shutdown |
||||
|
|
@ -0,0 +1,11 @@ |
|||||
|
Changelog |
||||
|
========= |
||||
|
|
||||
|
Jack Grigg (6): |
||||
|
Move libsnark from DIST_SUBDIRS into EXTRA_DIST |
||||
|
Pass correct dependencies path to libsnark from both Gitian and build.sh |
||||
|
Mark libsnark includes as library includes |
||||
|
Add the tar-pax option to automake |
||||
|
make-release.py: Versioning changes for 1.0.13-rc2. |
||||
|
make-release.py: Updated manpages for 1.0.13-rc2. |
||||
|
|
@ -0,0 +1,7 @@ |
|||||
|
Changelog |
||||
|
========= |
||||
|
|
||||
|
Jack Grigg (2): |
||||
|
make-release.py: Versioning changes for 1.0.13. |
||||
|
make-release.py: Updated manpages for 1.0.13. |
||||
|
|
@ -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() |
@ -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() |
@ -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() |
@ -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() |
@ -0,0 +1,882 @@ |
|||||
|
#!/bin/bash |
||||
|
# |
||||
|
# The BSD License (http://www.opensource.org/licenses/bsd-license.php) |
||||
|
# specifies the terms and conditions of use for checksec.sh: |
||||
|
# |
||||
|
# Copyright (c) 2009-2011, Tobias Klein. |
||||
|
# All rights reserved. |
||||
|
# |
||||
|
# Redistribution and use in source and binary forms, with or without |
||||
|
# modification, are permitted provided that the following conditions |
||||
|
# are met: |
||||
|
# |
||||
|
# * Redistributions of source code must retain the above copyright |
||||
|
# notice, this list of conditions and the following disclaimer. |
||||
|
# * Redistributions in binary form must reproduce the above copyright |
||||
|
# notice, this list of conditions and the following disclaimer in |
||||
|
# the documentation and/or other materials provided with the |
||||
|
# distribution. |
||||
|
# * Neither the name of Tobias Klein nor the name of trapkit.de may be |
||||
|
# used to endorse or promote products derived from this software |
||||
|
# without specific prior written permission. |
||||
|
# |
||||
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
|
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
|
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
||||
|
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |
||||
|
# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, |
||||
|
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
||||
|
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS |
||||
|
# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED |
||||
|
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, |
||||
|
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF |
||||
|
# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH |
||||
|
# DAMAGE. |
||||
|
# |
||||
|
# Name : checksec.sh |
||||
|
# Version : 1.5 |
||||
|
# Author : Tobias Klein |
||||
|
# Date : November 2011 |
||||
|
# Download: http://www.trapkit.de/tools/checksec.html |
||||
|
# Changes : http://www.trapkit.de/tools/checksec_changes.txt |
||||
|
# |
||||
|
# Description: |
||||
|
# |
||||
|
# Modern Linux distributions offer some mitigation techniques to make it |
||||
|
# harder to exploit software vulnerabilities reliably. Mitigations such |
||||
|
# as RELRO, NoExecute (NX), Stack Canaries, Address Space Layout |
||||
|
# Randomization (ASLR) and Position Independent Executables (PIE) have |
||||
|
# made reliably exploiting any vulnerabilities that do exist far more |
||||
|
# challenging. The checksec.sh script is designed to test what *standard* |
||||
|
# Linux OS and PaX (http://pax.grsecurity.net/) security features are being |
||||
|
# used. |
||||
|
# |
||||
|
# As of version 1.3 the script also lists the status of various Linux kernel |
||||
|
# protection mechanisms. |
||||
|
# |
||||
|
# Credits: |
||||
|
# |
||||
|
# Thanks to Brad Spengler (grsecurity.net) for the PaX support. |
||||
|
# Thanks to Jon Oberheide (jon.oberheide.org) for the kernel support. |
||||
|
# Thanks to Ollie Whitehouse (Research In Motion) for rpath/runpath support. |
||||
|
# |
||||
|
# Others that contributed to checksec.sh (in no particular order): |
||||
|
# |
||||
|
# Simon Ruderich, Denis Scherbakov, Stefan Kuttler, Radoslaw Madej, |
||||
|
# Anthony G. Basile, Martin Vaeth and Brian Davis. |
||||
|
# |
||||
|
|
||||
|
# global vars |
||||
|
have_readelf=1 |
||||
|
verbose=false |
||||
|
|
||||
|
# FORTIFY_SOURCE vars |
||||
|
FS_end=_chk |
||||
|
FS_cnt_total=0 |
||||
|
FS_cnt_checked=0 |
||||
|
FS_cnt_unchecked=0 |
||||
|
FS_chk_func_libc=0 |
||||
|
FS_functions=0 |
||||
|
FS_libc=0 |
||||
|
|
||||
|
# version information |
||||
|
version() { |
||||
|
echo "checksec v1.5, Tobias Klein, www.trapkit.de, November 2011" |
||||
|
echo |
||||
|
} |
||||
|
|
||||
|
# help |
||||
|
help() { |
||||
|
echo "Usage: checksec [OPTION]" |
||||
|
echo |
||||
|
echo "Options:" |
||||
|
echo |
||||
|
echo " --file <executable-file>" |
||||
|
echo " --dir <directory> [-v]" |
||||
|
echo " --proc <process name>" |
||||
|
echo " --proc-all" |
||||
|
echo " --proc-libs <process ID>" |
||||
|
echo " --kernel" |
||||
|
echo " --fortify-file <executable-file>" |
||||
|
echo " --fortify-proc <process ID>" |
||||
|
echo " --version" |
||||
|
echo " --help" |
||||
|
echo |
||||
|
echo "For more information, see:" |
||||
|
echo " http://www.trapkit.de/tools/checksec.html" |
||||
|
echo |
||||
|
} |
||||
|
|
||||
|
# check if command exists |
||||
|
command_exists () { |
||||
|
type $1 > /dev/null 2>&1; |
||||
|
} |
||||
|
|
||||
|
# check if directory exists |
||||
|
dir_exists () { |
||||
|
if [ -d $1 ] ; then |
||||
|
return 0 |
||||
|
else |
||||
|
return 1 |
||||
|
fi |
||||
|
} |
||||
|
|
||||
|
# check user privileges |
||||
|
root_privs () { |
||||
|
if [ $(/usr/bin/id -u) -eq 0 ] ; then |
||||
|
return 0 |
||||
|
else |
||||
|
return 1 |
||||
|
fi |
||||
|
} |
||||
|
|
||||
|
# check if input is numeric |
||||
|
isNumeric () { |
||||
|
echo "$@" | grep -q -v "[^0-9]" |
||||
|
} |
||||
|
|
||||
|
# check if input is a string |
||||
|
isString () { |
||||
|
echo "$@" | grep -q -v "[^A-Za-z]" |
||||
|
} |
||||
|
|
||||
|
# check file(s) |
||||
|
filecheck() { |
||||
|
# check for RELRO support |
||||
|
if readelf -l $1 2>/dev/null | grep -q 'GNU_RELRO'; then |
||||
|
if readelf -d $1 2>/dev/null | grep -q 'BIND_NOW'; then |
||||
|
echo -n -e '\033[32mFull RELRO \033[m ' |
||||
|
else |
||||
|
echo -n -e '\033[33mPartial RELRO\033[m ' |
||||
|
fi |
||||
|
else |
||||
|
echo -n -e '\033[31mNo RELRO \033[m ' |
||||
|
fi |
||||
|
|
||||
|
# check for stack canary support |
||||
|
if readelf -s $1 2>/dev/null | grep -q '__stack_chk_fail'; then |
||||
|
echo -n -e '\033[32mCanary found \033[m ' |
||||
|
else |
||||
|
echo -n -e '\033[31mNo canary found\033[m ' |
||||
|
fi |
||||
|
|
||||
|
# check for NX support |
||||
|
if readelf -W -l $1 2>/dev/null | grep 'GNU_STACK' | grep -q 'RWE'; then |
||||
|
echo -n -e '\033[31mNX disabled\033[m ' |
||||
|
else |
||||
|
echo -n -e '\033[32mNX enabled \033[m ' |
||||
|
fi |
||||
|
|
||||
|
# check for PIE support |
||||
|
if readelf -h $1 2>/dev/null | grep -q 'Type:[[:space:]]*EXEC'; then |
||||
|
echo -n -e '\033[31mNo PIE \033[m ' |
||||
|
elif readelf -h $1 2>/dev/null | grep -q 'Type:[[:space:]]*DYN'; then |
||||
|
if readelf -d $1 2>/dev/null | grep -q '(DEBUG)'; then |
||||
|
echo -n -e '\033[32mPIE enabled \033[m ' |
||||
|
else |
||||
|
echo -n -e '\033[33mDSO \033[m ' |
||||
|
fi |
||||
|
else |
||||
|
echo -n -e '\033[33mNot an ELF file\033[m ' |
||||
|
fi |
||||
|
|
||||
|
# check for rpath / run path |
||||
|
if readelf -d $1 2>/dev/null | grep -q 'rpath'; then |
||||
|
echo -n -e '\033[31mRPATH \033[m ' |
||||
|
else |
||||
|
echo -n -e '\033[32mNo RPATH \033[m ' |
||||
|
fi |
||||
|
|
||||
|
if readelf -d $1 2>/dev/null | grep -q 'runpath'; then |
||||
|
echo -n -e '\033[31mRUNPATH \033[m ' |
||||
|
else |
||||
|
echo -n -e '\033[32mNo RUNPATH \033[m ' |
||||
|
fi |
||||
|
} |
||||
|
|
||||
|
# check process(es) |
||||
|
proccheck() { |
||||
|
# check for RELRO support |
||||
|
if readelf -l $1/exe 2>/dev/null | grep -q 'Program Headers'; then |
||||
|
if readelf -l $1/exe 2>/dev/null | grep -q 'GNU_RELRO'; then |
||||
|
if readelf -d $1/exe 2>/dev/null | grep -q 'BIND_NOW'; then |
||||
|
echo -n -e '\033[32mFull RELRO \033[m ' |
||||
|
else |
||||
|
echo -n -e '\033[33mPartial RELRO \033[m ' |
||||
|
fi |
||||
|
else |
||||
|
echo -n -e '\033[31mNo RELRO \033[m ' |
||||
|
fi |
||||
|
else |
||||
|
echo -n -e '\033[31mPermission denied (please run as root)\033[m\n' |
||||
|
exit 1 |
||||
|
fi |
||||
|
|
||||
|
# check for stack canary support |
||||
|
if readelf -s $1/exe 2>/dev/null | grep -q 'Symbol table'; then |
||||
|
if readelf -s $1/exe 2>/dev/null | grep -q '__stack_chk_fail'; then |
||||
|
echo -n -e '\033[32mCanary found \033[m ' |
||||
|
else |
||||
|
echo -n -e '\033[31mNo canary found \033[m ' |
||||
|
fi |
||||
|
else |
||||
|
if [ "$1" != "1" ] ; then |
||||
|
echo -n -e '\033[33mPermission denied \033[m ' |
||||
|
else |
||||
|
echo -n -e '\033[33mNo symbol table found\033[m ' |
||||
|
fi |
||||
|
fi |
||||
|
|
||||
|
# first check for PaX support |
||||
|
if cat $1/status 2> /dev/null | grep -q 'PaX:'; then |
||||
|
pageexec=( $(cat $1/status 2> /dev/null | grep 'PaX:' | cut -b6) ) |
||||
|
segmexec=( $(cat $1/status 2> /dev/null | grep 'PaX:' | cut -b10) ) |
||||
|
mprotect=( $(cat $1/status 2> /dev/null | grep 'PaX:' | cut -b8) ) |
||||
|
randmmap=( $(cat $1/status 2> /dev/null | grep 'PaX:' | cut -b9) ) |
||||
|
if [[ "$pageexec" = "P" || "$segmexec" = "S" ]] && [[ "$mprotect" = "M" && "$randmmap" = "R" ]] ; then |
||||
|
echo -n -e '\033[32mPaX enabled\033[m ' |
||||
|
elif [[ "$pageexec" = "p" && "$segmexec" = "s" && "$randmmap" = "R" ]] ; then |
||||
|
echo -n -e '\033[33mPaX ASLR only\033[m ' |
||||
|
elif [[ "$pageexec" = "P" || "$segmexec" = "S" ]] && [[ "$mprotect" = "m" && "$randmmap" = "R" ]] ; then |
||||
|
echo -n -e '\033[33mPaX mprot off \033[m' |
||||
|
elif [[ "$pageexec" = "P" || "$segmexec" = "S" ]] && [[ "$mprotect" = "M" && "$randmmap" = "r" ]] ; then |
||||
|
echo -n -e '\033[33mPaX ASLR off\033[m ' |
||||
|
elif [[ "$pageexec" = "P" || "$segmexec" = "S" ]] && [[ "$mprotect" = "m" && "$randmmap" = "r" ]] ; then |
||||
|
echo -n -e '\033[33mPaX NX only\033[m ' |
||||
|
else |
||||
|
echo -n -e '\033[31mPaX disabled\033[m ' |
||||
|
fi |
||||
|
# fallback check for NX support |
||||
|
elif readelf -W -l $1/exe 2>/dev/null | grep 'GNU_STACK' | grep -q 'RWE'; then |
||||
|
echo -n -e '\033[31mNX disabled\033[m ' |
||||
|
else |
||||
|
echo -n -e '\033[32mNX enabled \033[m ' |
||||
|
fi |
||||
|
|
||||
|
# check for PIE support |
||||
|
if readelf -h $1/exe 2>/dev/null | grep -q 'Type:[[:space:]]*EXEC'; then |
||||
|
echo -n -e '\033[31mNo PIE \033[m ' |
||||
|
elif readelf -h $1/exe 2>/dev/null | grep -q 'Type:[[:space:]]*DYN'; then |
||||
|
if readelf -d $1/exe 2>/dev/null | grep -q '(DEBUG)'; then |
||||
|
echo -n -e '\033[32mPIE enabled \033[m ' |
||||
|
else |
||||
|
echo -n -e '\033[33mDynamic Shared Object\033[m ' |
||||
|
fi |
||||
|
else |
||||
|
echo -n -e '\033[33mNot an ELF file \033[m ' |
||||
|
fi |
||||
|
} |
||||
|
|
||||
|
# check mapped libraries |
||||
|
libcheck() { |
||||
|
libs=( $(awk '{ print $6 }' /proc/$1/maps | grep '/' | sort -u | xargs file | grep ELF | awk '{ print $1 }' | sed 's/:/ /') ) |
||||
|
|
||||
|
printf "\n* Loaded libraries (file information, # of mapped files: ${#libs[@]}):\n\n" |
||||
|
|
||||
|
for element in $(seq 0 $((${#libs[@]} - 1))) |
||||
|
do |
||||
|
echo " ${libs[$element]}:" |
||||
|
echo -n " " |
||||
|
filecheck ${libs[$element]} |
||||
|
printf "\n\n" |
||||
|
done |
||||
|
} |
||||
|
|
||||
|
# check for system-wide ASLR support |
||||
|
aslrcheck() { |
||||
|
# PaX ASLR support |
||||
|
if !(cat /proc/1/status 2> /dev/null | grep -q 'Name:') ; then |
||||
|
echo -n -e ':\033[33m insufficient privileges for PaX ASLR checks\033[m\n' |
||||
|
echo -n -e ' Fallback to standard Linux ASLR check' |
||||
|
fi |
||||
|
|
||||
|
if cat /proc/1/status 2> /dev/null | grep -q 'PaX:'; then |
||||
|
printf ": " |
||||
|
if cat /proc/1/status 2> /dev/null | grep 'PaX:' | grep -q 'R'; then |
||||
|
echo -n -e '\033[32mPaX ASLR enabled\033[m\n\n' |
||||
|
else |
||||
|
echo -n -e '\033[31mPaX ASLR disabled\033[m\n\n' |
||||
|
fi |
||||
|
else |
||||
|
# standard Linux 'kernel.randomize_va_space' ASLR support |
||||
|
# (see the kernel file 'Documentation/sysctl/kernel.txt' for a detailed description) |
||||
|
printf " (kernel.randomize_va_space): " |
||||
|
if /sbin/sysctl -a 2>/dev/null | grep -q 'kernel.randomize_va_space = 1'; then |
||||
|
echo -n -e '\033[33mOn (Setting: 1)\033[m\n\n' |
||||
|
printf " Description - Make the addresses of mmap base, stack and VDSO page randomized.\n" |
||||
|
printf " This, among other things, implies that shared libraries will be loaded to \n" |
||||
|
printf " random addresses. Also for PIE-linked binaries, the location of code start\n" |
||||
|
printf " is randomized. Heap addresses are *not* randomized.\n\n" |
||||
|
elif /sbin/sysctl -a 2>/dev/null | grep -q 'kernel.randomize_va_space = 2'; then |
||||
|
echo -n -e '\033[32mOn (Setting: 2)\033[m\n\n' |
||||
|
printf " Description - Make the addresses of mmap base, heap, stack and VDSO page randomized.\n" |
||||
|
printf " This, among other things, implies that shared libraries will be loaded to random \n" |
||||
|
printf " addresses. Also for PIE-linked binaries, the location of code start is randomized.\n\n" |
||||
|
elif /sbin/sysctl -a 2>/dev/null | grep -q 'kernel.randomize_va_space = 0'; then |
||||
|
echo -n -e '\033[31mOff (Setting: 0)\033[m\n' |
||||
|
else |
||||
|
echo -n -e '\033[31mNot supported\033[m\n' |
||||
|
fi |
||||
|
printf " See the kernel file 'Documentation/sysctl/kernel.txt' for more details.\n\n" |
||||
|
fi |
||||
|
} |
||||
|
|
||||
|
# check cpu nx flag |
||||
|
nxcheck() { |
||||
|
if grep -q nx /proc/cpuinfo; then |
||||
|
echo -n -e '\033[32mYes\033[m\n\n' |
||||
|
else |
||||
|
echo -n -e '\033[31mNo\033[m\n\n' |
||||
|
fi |
||||
|
} |
||||
|
|
||||
|
# check for kernel protection mechanisms |
||||
|
kernelcheck() { |
||||
|
printf " Description - List the status of kernel protection mechanisms. Rather than\n" |
||||
|
printf " inspect kernel mechanisms that may aid in the prevention of exploitation of\n" |
||||
|
printf " userspace processes, this option lists the status of kernel configuration\n" |
||||
|
printf " options that harden the kernel itself against attack.\n\n" |
||||
|
printf " Kernel config: " |
||||
|
|
||||
|
if [ -f /proc/config.gz ] ; then |
||||
|
kconfig="zcat /proc/config.gz" |
||||
|
printf "\033[32m/proc/config.gz\033[m\n\n" |
||||
|
elif [ -f /boot/config-`uname -r` ] ; then |
||||
|
kconfig="cat /boot/config-`uname -r`" |
||||
|
printf "\033[33m/boot/config-`uname -r`\033[m\n\n" |
||||
|
printf " Warning: The config on disk may not represent running kernel config!\n\n"; |
||||
|
elif [ -f "${KBUILD_OUTPUT:-/usr/src/linux}"/.config ] ; then |
||||
|
kconfig="cat ${KBUILD_OUTPUT:-/usr/src/linux}/.config" |
||||
|
printf "\033[33m%s\033[m\n\n" "${KBUILD_OUTPUT:-/usr/src/linux}/.config" |
||||
|
printf " Warning: The config on disk may not represent running kernel config!\n\n"; |
||||
|
else |
||||
|
printf "\033[31mNOT FOUND\033[m\n\n" |
||||
|
exit 0 |
||||
|
fi |
||||
|
|
||||
|
printf " GCC stack protector support: " |
||||
|
if $kconfig | grep -qi 'CONFIG_CC_STACKPROTECTOR=y'; then |
||||
|
printf "\033[32mEnabled\033[m\n" |
||||
|
else |
||||
|
printf "\033[31mDisabled\033[m\n" |
||||
|
fi |
||||
|
|
||||
|
printf " Strict user copy checks: " |
||||
|
if $kconfig | grep -qi 'CONFIG_DEBUG_STRICT_USER_COPY_CHECKS=y'; then |
||||
|
printf "\033[32mEnabled\033[m\n" |
||||
|
else |
||||
|
printf "\033[31mDisabled\033[m\n" |
||||
|
fi |
||||
|
|
||||
|
printf " Enforce read-only kernel data: " |
||||
|
if $kconfig | grep -qi 'CONFIG_DEBUG_RODATA=y'; then |
||||
|
printf "\033[32mEnabled\033[m\n" |
||||
|
else |
||||
|
printf "\033[31mDisabled\033[m\n" |
||||
|
fi |
||||
|
printf " Restrict /dev/mem access: " |
||||
|
if $kconfig | grep -qi 'CONFIG_STRICT_DEVMEM=y'; then |
||||
|
printf "\033[32mEnabled\033[m\n" |
||||
|
else |
||||
|
printf "\033[31mDisabled\033[m\n" |
||||
|
fi |
||||
|
|
||||
|
printf " Restrict /dev/kmem access: " |
||||
|
if $kconfig | grep -qi 'CONFIG_DEVKMEM=y'; then |
||||
|
printf "\033[31mDisabled\033[m\n" |
||||
|
else |
||||
|
printf "\033[32mEnabled\033[m\n" |
||||
|
fi |
||||
|
|
||||
|
printf "\n" |
||||
|
printf "* grsecurity / PaX: " |
||||
|
|
||||
|
if $kconfig | grep -qi 'CONFIG_GRKERNSEC=y'; then |
||||
|
if $kconfig | grep -qi 'CONFIG_GRKERNSEC_HIGH=y'; then |
||||
|
printf "\033[32mHigh GRKERNSEC\033[m\n\n" |
||||
|
elif $kconfig | grep -qi 'CONFIG_GRKERNSEC_MEDIUM=y'; then |
||||
|
printf "\033[33mMedium GRKERNSEC\033[m\n\n" |
||||
|
elif $kconfig | grep -qi 'CONFIG_GRKERNSEC_LOW=y'; then |
||||
|
printf "\033[31mLow GRKERNSEC\033[m\n\n" |
||||
|
else |
||||
|
printf "\033[33mCustom GRKERNSEC\033[m\n\n" |
||||
|
fi |
||||
|
|
||||
|
printf " Non-executable kernel pages: " |
||||
|
if $kconfig | grep -qi 'CONFIG_PAX_KERNEXEC=y'; then |
||||
|
printf "\033[32mEnabled\033[m\n" |
||||
|
else |
||||
|
printf "\033[31mDisabled\033[m\n" |
||||
|
fi |
||||
|
|
||||
|
printf " Prevent userspace pointer deref: " |
||||
|
if $kconfig | grep -qi 'CONFIG_PAX_MEMORY_UDEREF=y'; then |
||||
|
printf "\033[32mEnabled\033[m\n" |
||||
|
else |
||||
|
printf "\033[31mDisabled\033[m\n" |
||||
|
fi |
||||
|
|
||||
|
printf " Prevent kobject refcount overflow: " |
||||
|
if $kconfig | grep -qi 'CONFIG_PAX_REFCOUNT=y'; then |
||||
|
printf "\033[32mEnabled\033[m\n" |
||||
|
else |
||||
|
printf "\033[31mDisabled\033[m\n" |
||||
|
fi |
||||
|
|
||||
|
printf " Bounds check heap object copies: " |
||||
|
if $kconfig | grep -qi 'CONFIG_PAX_USERCOPY=y'; then |
||||
|
printf "\033[32mEnabled\033[m\n" |
||||
|
else |
||||
|
printf "\033[31mDisabled\033[m\n" |
||||
|
fi |
||||
|
|
||||
|
printf " Disable writing to kmem/mem/port: " |
||||
|
if $kconfig | grep -qi 'CONFIG_GRKERNSEC_KMEM=y'; then |
||||
|
printf "\033[32mEnabled\033[m\n" |
||||
|
else |
||||
|
printf "\033[31mDisabled\033[m\n" |
||||
|
fi |
||||
|
|
||||
|
printf " Disable privileged I/O: " |
||||
|
if $kconfig | grep -qi 'CONFIG_GRKERNSEC_IO=y'; then |
||||
|
printf "\033[32mEnabled\033[m\n" |
||||
|
else |
||||
|
printf "\033[31mDisabled\033[m\n" |
||||
|
fi |
||||
|
|
||||
|
printf " Harden module auto-loading: " |
||||
|
if $kconfig | grep -qi 'CONFIG_GRKERNSEC_MODHARDEN=y'; then |
||||
|
printf "\033[32mEnabled\033[m\n" |
||||
|
else |
||||
|
printf "\033[31mDisabled\033[m\n" |
||||
|
fi |
||||
|
|
||||
|
printf " Hide kernel symbols: " |
||||
|
if $kconfig | grep -qi 'CONFIG_GRKERNSEC_HIDESYM=y'; then |
||||
|
printf "\033[32mEnabled\033[m\n" |
||||
|
else |
||||
|
printf "\033[31mDisabled\033[m\n" |
||||
|
fi |
||||
|
else |
||||
|
printf "\033[31mNo GRKERNSEC\033[m\n\n" |
||||
|
printf " The grsecurity / PaX patchset is available here:\n" |
||||
|
printf " http://grsecurity.net/\n" |
||||
|
fi |
||||
|
|
||||
|
printf "\n" |
||||
|
printf "* Kernel Heap Hardening: " |
||||
|
|
||||
|
if $kconfig | grep -qi 'CONFIG_KERNHEAP=y'; then |
||||
|
if $kconfig | grep -qi 'CONFIG_KERNHEAP_FULLPOISON=y'; then |
||||
|
printf "\033[32mFull KERNHEAP\033[m\n\n" |
||||
|
else |
||||
|
printf "\033[33mPartial KERNHEAP\033[m\n\n" |
||||
|
fi |
||||
|
else |
||||
|
printf "\033[31mNo KERNHEAP\033[m\n\n" |
||||
|
printf " The KERNHEAP hardening patchset is available here:\n" |
||||
|
printf " https://www.subreption.com/kernheap/\n\n" |
||||
|
fi |
||||
|
} |
||||
|
|
||||
|
# --- FORTIFY_SOURCE subfunctions (start) --- |
||||
|
|
||||
|
# is FORTIFY_SOURCE supported by libc? |
||||
|
FS_libc_check() { |
||||
|
printf "* FORTIFY_SOURCE support available (libc) : " |
||||
|
|
||||
|
if [ "${#FS_chk_func_libc[@]}" != "0" ] ; then |
||||
|
printf "\033[32mYes\033[m\n" |
||||
|
else |
||||
|
printf "\033[31mNo\033[m\n" |
||||
|
exit 1 |
||||
|
fi |
||||
|
} |
||||
|
|
||||
|
# was the binary compiled with FORTIFY_SOURCE? |
||||
|
FS_binary_check() { |
||||
|
printf "* Binary compiled with FORTIFY_SOURCE support: " |
||||
|
|
||||
|
for FS_elem_functions in $(seq 0 $((${#FS_functions[@]} - 1))) |
||||
|
do |
||||
|
if [[ ${FS_functions[$FS_elem_functions]} =~ _chk ]] ; then |
||||
|
printf "\033[32mYes\033[m\n" |
||||
|
return |
||||
|
fi |
||||
|
done |
||||
|
printf "\033[31mNo\033[m\n" |
||||
|
exit 1 |
||||
|
} |
||||
|
|
||||
|
FS_comparison() { |
||||
|
echo |
||||
|
printf " ------ EXECUTABLE-FILE ------- . -------- LIBC --------\n" |
||||
|
printf " FORTIFY-able library functions | Checked function names\n" |
||||
|
printf " -------------------------------------------------------\n" |
||||
|
|
||||
|
for FS_elem_libc in $(seq 0 $((${#FS_chk_func_libc[@]} - 1))) |
||||
|
do |
||||
|
for FS_elem_functions in $(seq 0 $((${#FS_functions[@]} - 1))) |
||||
|
do |
||||
|
FS_tmp_func=${FS_functions[$FS_elem_functions]} |
||||
|
FS_tmp_libc=${FS_chk_func_libc[$FS_elem_libc]} |
||||
|
|
||||
|
if [[ $FS_tmp_func =~ ^$FS_tmp_libc$ ]] ; then |
||||
|
printf " \033[31m%-30s\033[m | __%s%s\n" $FS_tmp_func $FS_tmp_libc $FS_end |
||||
|
let FS_cnt_total++ |
||||
|
let FS_cnt_unchecked++ |
||||
|
elif [[ $FS_tmp_func =~ ^$FS_tmp_libc(_chk) ]] ; then |
||||
|
printf " \033[32m%-30s\033[m | __%s%s\n" $FS_tmp_func $FS_tmp_libc $FS_end |
||||
|
let FS_cnt_total++ |
||||
|
let FS_cnt_checked++ |
||||
|
fi |
||||
|
|
||||
|
done |
||||
|
done |
||||
|
} |
||||
|
|
||||
|
FS_summary() { |
||||
|
echo |
||||
|
printf "SUMMARY:\n\n" |
||||
|
printf "* Number of checked functions in libc : ${#FS_chk_func_libc[@]}\n" |
||||
|
printf "* Total number of library functions in the executable: ${#FS_functions[@]}\n" |
||||
|
printf "* Number of FORTIFY-able functions in the executable : %s\n" $FS_cnt_total |
||||
|
printf "* Number of checked functions in the executable : \033[32m%s\033[m\n" $FS_cnt_checked |
||||
|
printf "* Number of unchecked functions in the executable : \033[31m%s\033[m\n" $FS_cnt_unchecked |
||||
|
echo |
||||
|
} |
||||
|
|
||||
|
# --- FORTIFY_SOURCE subfunctions (end) --- |
||||
|
|
||||
|
if !(command_exists readelf) ; then |
||||
|
printf "\033[31mWarning: 'readelf' not found! It's required for most checks.\033[m\n\n" |
||||
|
have_readelf=0 |
||||
|
fi |
||||
|
|
||||
|
# parse command-line arguments |
||||
|
case "$1" in |
||||
|
|
||||
|
--version) |
||||
|
version |
||||
|
exit 0 |
||||
|
;; |
||||
|
|
||||
|
--help) |
||||
|
help |
||||
|
exit 0 |
||||
|
;; |
||||
|
|
||||
|
--dir) |
||||
|
if [ "$3" = "-v" ] ; then |
||||
|
verbose=true |
||||
|
fi |
||||
|
if [ $have_readelf -eq 0 ] ; then |
||||
|
exit 1 |
||||
|
fi |
||||
|
if [ -z "$2" ] ; then |
||||
|
printf "\033[31mError: Please provide a valid directory.\033[m\n\n" |
||||
|
exit 1 |
||||
|
fi |
||||
|
# remove trailing slashes |
||||
|
tempdir=`echo $2 | sed -e "s/\/*$//"` |
||||
|
if [ ! -d $tempdir ] ; then |
||||
|
printf "\033[31mError: The directory '$tempdir' does not exist.\033[m\n\n" |
||||
|
exit 1 |
||||
|
fi |
||||
|
cd $tempdir |
||||
|
printf "RELRO STACK CANARY NX PIE RPATH RUNPATH FILE\n" |
||||
|
for N in [A-Za-z]*; do |
||||
|
if [ "$N" != "[A-Za-z]*" ]; then |
||||
|
# read permissions? |
||||
|
if [ ! -r $N ]; then |
||||
|
printf "\033[31mError: No read permissions for '$tempdir/$N' (run as root).\033[m\n" |
||||
|
else |
||||
|
# ELF executable? |
||||
|
out=`file $N` |
||||
|
if [[ ! $out =~ ELF ]] ; then |
||||
|
if [ "$verbose" = "true" ] ; then |
||||
|
printf "\033[34m*** Not an ELF file: $tempdir/" |
||||
|
file $N |
||||
|
printf "\033[m" |
||||
|
fi |
||||
|
else |
||||
|
filecheck $N |
||||
|
if [ `find $tempdir/$N \( -perm -004000 -o -perm -002000 \) -type f -print` ]; then |
||||
|
printf "\033[37;41m%s%s\033[m" $2 $N |
||||
|
else |
||||
|
printf "%s%s" $tempdir/ $N |
||||
|
fi |
||||
|
echo |
||||
|
fi |
||||
|
fi |
||||
|
fi |
||||
|
done |
||||
|
exit 0 |
||||
|
;; |
||||
|
|
||||
|
--file) |
||||
|
if [ $have_readelf -eq 0 ] ; then |
||||
|
exit 1 |
||||
|
fi |
||||
|
if [ -z "$2" ] ; then |
||||
|
printf "\033[31mError: Please provide a valid file.\033[m\n\n" |
||||
|
exit 1 |
||||
|
fi |
||||
|
# does the file exist? |
||||
|
if [ ! -e $2 ] ; then |
||||
|
printf "\033[31mError: The file '$2' does not exist.\033[m\n\n" |
||||
|
exit 1 |
||||
|
fi |
||||
|
# read permissions? |
||||
|
if [ ! -r $2 ] ; then |
||||
|
printf "\033[31mError: No read permissions for '$2' (run as root).\033[m\n\n" |
||||
|
exit 1 |
||||
|
fi |
||||
|
# ELF executable? |
||||
|
out=`file $2` |
||||
|
if [[ ! $out =~ ELF ]] ; then |
||||
|
printf "\033[31mError: Not an ELF file: " |
||||
|
file $2 |
||||
|
printf "\033[m\n" |
||||
|
exit 1 |
||||
|
fi |
||||
|
printf "RELRO STACK CANARY NX PIE RPATH RUNPATH FILE\n" |
||||
|
filecheck $2 |
||||
|
if [ `find $2 \( -perm -004000 -o -perm -002000 \) -type f -print` ] ; then |
||||
|
printf "\033[37;41m%s%s\033[m" $2 $N |
||||
|
else |
||||
|
printf "%s" $2 |
||||
|
fi |
||||
|
echo |
||||
|
exit 0 |
||||
|
;; |
||||
|
|
||||
|
--proc-all) |
||||
|
if [ $have_readelf -eq 0 ] ; then |
||||
|
exit 1 |
||||
|
fi |
||||
|
cd /proc |
||||
|
printf "* System-wide ASLR" |
||||
|
aslrcheck |
||||
|
printf "* Does the CPU support NX: " |
||||
|
nxcheck |
||||
|
printf " COMMAND PID RELRO STACK CANARY NX/PaX PIE\n" |
||||
|
for N in [1-9]*; do |
||||
|
if [ $N != $$ ] && readlink -q $N/exe > /dev/null; then |
||||
|
printf "%16s" `head -1 $N/status | cut -b 7-` |
||||
|
printf "%7d " $N |
||||
|
proccheck $N |
||||
|
echo |
||||
|
fi |
||||
|
done |
||||
|
if [ ! -e /usr/bin/id ] ; then |
||||
|
printf "\n\033[33mNote: If you are running 'checksec.sh' as an unprivileged user, you\n" |
||||
|
printf " will not see all processes. Please run the script as root.\033[m\n\n" |
||||
|
else |
||||
|
if !(root_privs) ; then |
||||
|
printf "\n\033[33mNote: You are running 'checksec.sh' as an unprivileged user.\n" |
||||
|
printf " Too see all processes, please run the script as root.\033[m\n\n" |
||||
|
fi |
||||
|
fi |
||||
|
exit 0 |
||||
|
;; |
||||
|
|
||||
|
--proc) |
||||
|
if [ $have_readelf -eq 0 ] ; then |
||||
|
exit 1 |
||||
|
fi |
||||
|
if [ -z "$2" ] ; then |
||||
|
printf "\033[31mError: Please provide a valid process name.\033[m\n\n" |
||||
|
exit 1 |
||||
|
fi |
||||
|
if !(isString "$2") ; then |
||||
|
printf "\033[31mError: Please provide a valid process name.\033[m\n\n" |
||||
|
exit 1 |
||||
|
fi |
||||
|
cd /proc |
||||
|
printf "* System-wide ASLR" |
||||
|
aslrcheck |
||||
|
printf "* Does the CPU support NX: " |
||||
|
nxcheck |
||||
|
printf " COMMAND PID RELRO STACK CANARY NX/PaX PIE\n" |
||||
|
for N in `ps -Ao pid,comm | grep $2 | cut -b1-6`; do |
||||
|
if [ -d $N ] ; then |
||||
|
printf "%16s" `head -1 $N/status | cut -b 7-` |
||||
|
printf "%7d " $N |
||||
|
# read permissions? |
||||
|
if [ ! -r $N/exe ] ; then |
||||
|
if !(root_privs) ; then |
||||
|
printf "\033[31mNo read permissions for '/proc/$N/exe' (run as root).\033[m\n\n" |
||||
|
exit 1 |
||||
|
fi |
||||
|
if [ ! `readlink $N/exe` ] ; then |
||||
|
printf "\033[31mPermission denied. Requested process ID belongs to a kernel thread.\033[m\n\n" |
||||
|
exit 1 |
||||
|
fi |
||||
|
exit 1 |
||||
|
fi |
||||
|
proccheck $N |
||||
|
echo |
||||
|
fi |
||||
|
done |
||||
|
exit 0 |
||||
|
;; |
||||
|
|
||||
|
--proc-libs) |
||||
|
if [ $have_readelf -eq 0 ] ; then |
||||
|
exit 1 |
||||
|
fi |
||||
|
if [ -z "$2" ] ; then |
||||
|
printf "\033[31mError: Please provide a valid process ID.\033[m\n\n" |
||||
|
exit 1 |
||||
|
fi |
||||
|
if !(isNumeric "$2") ; then |
||||
|
printf "\033[31mError: Please provide a valid process ID.\033[m\n\n" |
||||
|
exit 1 |
||||
|
fi |
||||
|
cd /proc |
||||
|
printf "* System-wide ASLR" |
||||
|
aslrcheck |
||||
|
printf "* Does the CPU support NX: " |
||||
|
nxcheck |
||||
|
printf "* Process information:\n\n" |
||||
|
printf " COMMAND PID RELRO STACK CANARY NX/PaX PIE\n" |
||||
|
N=$2 |
||||
|
if [ -d $N ] ; then |
||||
|
printf "%16s" `head -1 $N/status | cut -b 7-` |
||||
|
printf "%7d " $N |
||||
|
# read permissions? |
||||
|
if [ ! -r $N/exe ] ; then |
||||
|
if !(root_privs) ; then |
||||
|
printf "\033[31mNo read permissions for '/proc/$N/exe' (run as root).\033[m\n\n" |
||||
|
exit 1 |
||||
|
fi |
||||
|
if [ ! `readlink $N/exe` ] ; then |
||||
|
printf "\033[31mPermission denied. Requested process ID belongs to a kernel thread.\033[m\n\n" |
||||
|
exit 1 |
||||
|
fi |
||||
|
exit 1 |
||||
|
fi |
||||
|
proccheck $N |
||||
|
echo |
||||
|
libcheck $N |
||||
|
fi |
||||
|
exit 0 |
||||
|
;; |
||||
|
|
||||
|
--kernel) |
||||
|
cd /proc |
||||
|
printf "* Kernel protection information:\n\n" |
||||
|
kernelcheck |
||||
|
exit 0 |
||||
|
;; |
||||
|
|
||||
|
--fortify-file) |
||||
|
if [ $have_readelf -eq 0 ] ; then |
||||
|
exit 1 |
||||
|
fi |
||||
|
if [ -z "$2" ] ; then |
||||
|
printf "\033[31mError: Please provide a valid file.\033[m\n\n" |
||||
|
exit 1 |
||||
|
fi |
||||
|
# does the file exist? |
||||
|
if [ ! -e $2 ] ; then |
||||
|
printf "\033[31mError: The file '$2' does not exist.\033[m\n\n" |
||||
|
exit 1 |
||||
|
fi |
||||
|
# read permissions? |
||||
|
if [ ! -r $2 ] ; then |
||||
|
printf "\033[31mError: No read permissions for '$2' (run as root).\033[m\n\n" |
||||
|
exit 1 |
||||
|
fi |
||||
|
# ELF executable? |
||||
|
out=`file $2` |
||||
|
if [[ ! $out =~ ELF ]] ; then |
||||
|
printf "\033[31mError: Not an ELF file: " |
||||
|
file $2 |
||||
|
printf "\033[m\n" |
||||
|
exit 1 |
||||
|
fi |
||||
|
if [ -e /lib/libc.so.6 ] ; then |
||||
|
FS_libc=/lib/libc.so.6 |
||||
|
elif [ -e /lib64/libc.so.6 ] ; then |
||||
|
FS_libc=/lib64/libc.so.6 |
||||
|
elif [ -e /lib/i386-linux-gnu/libc.so.6 ] ; then |
||||
|
FS_libc=/lib/i386-linux-gnu/libc.so.6 |
||||
|
elif [ -e /lib/x86_64-linux-gnu/libc.so.6 ] ; then |
||||
|
FS_libc=/lib/x86_64-linux-gnu/libc.so.6 |
||||
|
else |
||||
|
printf "\033[31mError: libc not found.\033[m\n\n" |
||||
|
exit 1 |
||||
|
fi |
||||
|
|
||||
|
FS_chk_func_libc=( $(readelf -s $FS_libc | grep _chk@@ | awk '{ print $8 }' | cut -c 3- | sed -e 's/_chk@.*//') ) |
||||
|
FS_functions=( $(readelf -s $2 | awk '{ print $8 }' | sed 's/_*//' | sed -e 's/@.*//') ) |
||||
|
|
||||
|
FS_libc_check |
||||
|
FS_binary_check |
||||
|
FS_comparison |
||||
|
FS_summary |
||||
|
|
||||
|
exit 0 |
||||
|
;; |
||||
|
|
||||
|
--fortify-proc) |
||||
|
if [ $have_readelf -eq 0 ] ; then |
||||
|
exit 1 |
||||
|
fi |
||||
|
if [ -z "$2" ] ; then |
||||
|
printf "\033[31mError: Please provide a valid process ID.\033[m\n\n" |
||||
|
exit 1 |
||||
|
fi |
||||
|
if !(isNumeric "$2") ; then |
||||
|
printf "\033[31mError: Please provide a valid process ID.\033[m\n\n" |
||||
|
exit 1 |
||||
|
fi |
||||
|
cd /proc |
||||
|
N=$2 |
||||
|
if [ -d $N ] ; then |
||||
|
# read permissions? |
||||
|
if [ ! -r $N/exe ] ; then |
||||
|
if !(root_privs) ; then |
||||
|
printf "\033[31mNo read permissions for '/proc/$N/exe' (run as root).\033[m\n\n" |
||||
|
exit 1 |
||||
|
fi |
||||
|
if [ ! `readlink $N/exe` ] ; then |
||||
|
printf "\033[31mPermission denied. Requested process ID belongs to a kernel thread.\033[m\n\n" |
||||
|
exit 1 |
||||
|
fi |
||||
|
exit 1 |
||||
|
fi |
||||
|
if [ -e /lib/libc.so.6 ] ; then |
||||
|
FS_libc=/lib/libc.so.6 |
||||
|
elif [ -e /lib64/libc.so.6 ] ; then |
||||
|
FS_libc=/lib64/libc.so.6 |
||||
|
elif [ -e /lib/i386-linux-gnu/libc.so.6 ] ; then |
||||
|
FS_libc=/lib/i386-linux-gnu/libc.so.6 |
||||
|
elif [ -e /lib/x86_64-linux-gnu/libc.so.6 ] ; then |
||||
|
FS_libc=/lib/x86_64-linux-gnu/libc.so.6 |
||||
|
else |
||||
|
printf "\033[31mError: libc not found.\033[m\n\n" |
||||
|
exit 1 |
||||
|
fi |
||||
|
printf "* Process name (PID) : %s (%d)\n" `head -1 $N/status | cut -b 7-` $N |
||||
|
FS_chk_func_libc=( $(readelf -s $FS_libc | grep _chk@@ | awk '{ print $8 }' | cut -c 3- | sed -e 's/_chk@.*//') ) |
||||
|
FS_functions=( $(readelf -s $2/exe | awk '{ print $8 }' | sed 's/_*//' | sed -e 's/@.*//') ) |
||||
|
|
||||
|
FS_libc_check |
||||
|
FS_binary_check |
||||
|
FS_comparison |
||||
|
FS_summary |
||||
|
fi |
||||
|
exit 0 |
||||
|
;; |
||||
|
|
||||
|
*) |
||||
|
if [ "$#" != "0" ] ; then |
||||
|
printf "\033[31mError: Unknown option '$1'.\033[m\n\n" |
||||
|
fi |
||||
|
help |
||||
|
exit 1 |
||||
|
;; |
||||
|
esac |
@ -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') |
@ -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() |
@ -0,0 +1,201 @@ |
|||||
|
#!/usr/bin/env python2 |
||||
|
# |
||||
|
# Execute all of the automated tests related to Zcash. |
||||
|
# |
||||
|
|
||||
|
import argparse |
||||
|
import os |
||||
|
import re |
||||
|
import subprocess |
||||
|
import sys |
||||
|
|
||||
|
REPOROOT = os.path.dirname( |
||||
|
os.path.dirname( |
||||
|
os.path.dirname( |
||||
|
os.path.abspath(__file__) |
||||
|
) |
||||
|
) |
||||
|
) |
||||
|
|
||||
|
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')], |
||||
|
} |
||||
|
|
||||
|
|
||||
|
# |
||||
|
# Test driver |
||||
|
# |
||||
|
|
||||
|
def run_stage(stage): |
||||
|
print('Running stage %s' % stage) |
||||
|
print('=' * (len(stage) + 14)) |
||||
|
print |
||||
|
|
||||
|
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() |
@ -0,0 +1,341 @@ |
|||||
|
#!/bin/bash |
||||
|
set -u |
||||
|
|
||||
|
|
||||
|
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" -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 { |
||||
|
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 $ZCASHD_PID |
||||
|
} |
||||
|
|
||||
|
function zcashd_massif_start { |
||||
|
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 { |
||||
|
zcash_rpc stop > /dev/null |
||||
|
wait $ZCASHD_PID |
||||
|
ms_print massif.out |
||||
|
} |
||||
|
|
||||
|
function zcashd_valgrind_start { |
||||
|
rm -rf "$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 { |
||||
|
zcash_rpc stop > /dev/null |
||||
|
wait $ZCASHD_PID |
||||
|
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 "${@:2}" |
||||
|
RAWJOINSPLIT=$(zcash_rpc zcsamplejoinsplit) |
||||
|
zcashd_stop |
||||
|
esac |
||||
|
esac |
||||
|
|
||||
|
case "$1" in |
||||
|
time) |
||||
|
zcashd_start "${@:2}" |
||||
|
case "$2" in |
||||
|
sleep) |
||||
|
zcash_rpc zcbenchmark sleep 10 |
||||
|
;; |
||||
|
parameterloading) |
||||
|
zcash_rpc zcbenchmark parameterloading 10 |
||||
|
;; |
||||
|
createjoinsplit) |
||||
|
zcash_rpc zcbenchmark createjoinsplit 10 "${@:3}" |
||||
|
;; |
||||
|
verifyjoinsplit) |
||||
|
zcash_rpc zcbenchmark verifyjoinsplit 1000 "\"$RAWJOINSPLIT\"" |
||||
|
;; |
||||
|
solveequihash) |
||||
|
zcash_rpc_slow zcbenchmark solveequihash 50 "${@:3}" |
||||
|
;; |
||||
|
verifyequihash) |
||||
|
zcash_rpc zcbenchmark verifyequihash 1000 |
||||
|
;; |
||||
|
validatelargetx) |
||||
|
zcash_rpc zcbenchmark validatelargetx 5 |
||||
|
;; |
||||
|
trydecryptnotes) |
||||
|
zcash_rpc zcbenchmark trydecryptnotes 1000 "${@:3}" |
||||
|
;; |
||||
|
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 to time." |
||||
|
exit 1 |
||||
|
esac |
||||
|
zcashd_stop |
||||
|
;; |
||||
|
memory) |
||||
|
zcashd_massif_start "${@:2}" |
||||
|
case "$2" in |
||||
|
sleep) |
||||
|
zcash_rpc zcbenchmark sleep 1 |
||||
|
;; |
||||
|
parameterloading) |
||||
|
zcash_rpc zcbenchmark parameterloading 1 |
||||
|
;; |
||||
|
createjoinsplit) |
||||
|
zcash_rpc_slow zcbenchmark createjoinsplit 1 "${@:3}" |
||||
|
;; |
||||
|
verifyjoinsplit) |
||||
|
zcash_rpc zcbenchmark verifyjoinsplit 1 "\"$RAWJOINSPLIT\"" |
||||
|
;; |
||||
|
solveequihash) |
||||
|
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 to memory." |
||||
|
exit 1 |
||||
|
esac |
||||
|
zcashd_massif_stop |
||||
|
rm -f massif.out |
||||
|
;; |
||||
|
valgrind) |
||||
|
zcashd_valgrind_start |
||||
|
case "$2" in |
||||
|
sleep) |
||||
|
zcash_rpc zcbenchmark sleep 1 |
||||
|
;; |
||||
|
parameterloading) |
||||
|
zcash_rpc zcbenchmark parameterloading 1 |
||||
|
;; |
||||
|
createjoinsplit) |
||||
|
zcash_rpc_veryslow zcbenchmark createjoinsplit 1 "${@:3}" |
||||
|
;; |
||||
|
verifyjoinsplit) |
||||
|
zcash_rpc zcbenchmark verifyjoinsplit 1 "\"$RAWJOINSPLIT\"" |
||||
|
;; |
||||
|
solveequihash) |
||||
|
zcash_rpc_veryslow zcbenchmark solveequihash 1 "${@:3}" |
||||
|
;; |
||||
|
verifyequihash) |
||||
|
zcash_rpc zcbenchmark verifyequihash 1 |
||||
|
;; |
||||
|
trydecryptnotes) |
||||
|
zcash_rpc zcbenchmark trydecryptnotes 1 "${@:3}" |
||||
|
;; |
||||
|
incnotewitnesses) |
||||
|
zcash_rpc zcbenchmark incnotewitnesses 1 "${@:3}" |
||||
|
;; |
||||
|
connectblockslow) |
||||
|
extract_benchmark_data |
||||
|
zcash_rpc zcbenchmark connectblockslow 1 |
||||
|
;; |
||||
|
*) |
||||
|
zcashd_valgrind_stop |
||||
|
echo "Bad arguments to valgrind." |
||||
|
exit 1 |
||||
|
esac |
||||
|
zcashd_valgrind_stop |
||||
|
rm -f valgrind.out |
||||
|
;; |
||||
|
valgrind-tests) |
||||
|
case "$2" in |
||||
|
gtest) |
||||
|
rm -f valgrind.out |
||||
|
valgrind --leak-check=yes -v --error-limit=no --log-file="valgrind.out" ./src/zcash-gtest |
||||
|
cat valgrind.out |
||||
|
rm -f valgrind.out |
||||
|
;; |
||||
|
test_bitcoin) |
||||
|
rm -f valgrind.out |
||||
|
valgrind --leak-check=yes -v --error-limit=no --log-file="valgrind.out" ./src/test/test_bitcoin |
||||
|
cat valgrind.out |
||||
|
rm -f valgrind.out |
||||
|
;; |
||||
|
*) |
||||
|
echo "Bad arguments to valgrind-tests." |
||||
|
exit 1 |
||||
|
esac |
||||
|
;; |
||||
|
*) |
||||
|
echo "Invalid benchmark type." |
||||
|
exit 1 |
||||
|
esac |
||||
|
|
||||
|
# Cleanup |
||||
|
rm -rf "$DATADIR" |
@ -0,0 +1,43 @@ |
|||||
|
#!/usr/bin/env python2 |
||||
|
|
||||
|
# This script tests that the package mirror at https://z.cash/depends-sources/ |
||||
|
# contains all of the packages required to build this version of Zcash. |
||||
|
# |
||||
|
# This script assumes you've just built Zcash, and that as a result of that |
||||
|
# build, all of the dependency packages have been downloaded into the |
||||
|
# depends/sources directory (inside the root of this repository). The script |
||||
|
# checks that all of those files are accessible on the mirror. |
||||
|
|
||||
|
import sys |
||||
|
import os |
||||
|
import requests |
||||
|
|
||||
|
MIRROR_URL_DIR="https://z.cash/depends-sources/" |
||||
|
DEPENDS_SOURCES_DIR=os.path.realpath(os.path.join( |
||||
|
os.path.dirname(__file__), |
||||
|
"..", "..", "depends", "sources" |
||||
|
)) |
||||
|
|
||||
|
def get_depends_sources_list(): |
||||
|
return filter( |
||||
|
lambda f: os.path.isfile(os.path.join(DEPENDS_SOURCES_DIR, f)), |
||||
|
os.listdir(DEPENDS_SOURCES_DIR) |
||||
|
) |
||||
|
|
||||
|
for filename in get_depends_sources_list(): |
||||
|
resp = requests.head(MIRROR_URL_DIR + filename) |
||||
|
|
||||
|
print "Checking [" + filename + "] ..." |
||||
|
|
||||
|
if resp.status_code != 200: |
||||
|
print "FAIL. File not found on server: " + filename |
||||
|
sys.exit(1) |
||||
|
|
||||
|
expected_size = os.path.getsize(os.path.join(DEPENDS_SOURCES_DIR, filename)) |
||||
|
server_size = int(resp.headers['Content-Length']) |
||||
|
if expected_size != server_size: |
||||
|
print "FAIL. On the server, %s is %d bytes, but locally it is %d bytes." % (filename, server_size, expected_size) |
||||
|
sys.exit(1) |
||||
|
|
||||
|
print "PASS." |
||||
|
sys.exit(0) |
@ -1,15 +1,15 @@ |
|||||
bitcoin ICON "pixmaps/bitcoin.ico" |
bitcoin ICON "pixmaps/bitcoin.ico" |
||||
|
|
||||
#include "wx/msw/wx.rc" |
#include "wx/msw/wx.rc" |
||||
|
|
||||
check ICON "pixmaps/check.ico" |
check ICON "pixmaps/check.ico" |
||||
send16 BITMAP "pixmaps/send16.bmp" |
send16 BITMAP "pixmaps/send16.bmp" |
||||
send16mask BITMAP "pixmaps/send16mask.bmp" |
send16mask BITMAP "pixmaps/send16mask.bmp" |
||||
send16masknoshadow BITMAP "pixmaps/send16masknoshadow.bmp" |
send16masknoshadow BITMAP "pixmaps/send16masknoshadow.bmp" |
||||
send20 BITMAP "pixmaps/send20.bmp" |
send20 BITMAP "pixmaps/send20.bmp" |
||||
send20mask BITMAP "pixmaps/send20mask.bmp" |
send20mask BITMAP "pixmaps/send20mask.bmp" |
||||
addressbook16 BITMAP "pixmaps/addressbook16.bmp" |
addressbook16 BITMAP "pixmaps/addressbook16.bmp" |
||||
addressbook16mask BITMAP "pixmaps/addressbook16mask.bmp" |
addressbook16mask BITMAP "pixmaps/addressbook16mask.bmp" |
||||
addressbook20 BITMAP "pixmaps/addressbook20.bmp" |
addressbook20 BITMAP "pixmaps/addressbook20.bmp" |
||||
addressbook20mask BITMAP "pixmaps/addressbook20mask.bmp" |
addressbook20mask BITMAP "pixmaps/addressbook20mask.bmp" |
||||
favicon ICON "pixmaps/favicon.ico" |
favicon ICON "pixmaps/favicon.ico" |
@ -0,0 +1,82 @@ |
|||||
|
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
|
// Copyright (c) 2009-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.
|
||||
|
|
||||
|
#ifndef BITCOIN_ADDRESSINDEX_H |
||||
|
#define BITCOIN_ADDRESSINDEX_H |
||||
|
|
||||
|
#include "uint256.h" |
||||
|
#include "amount.h" |
||||
|
|
||||
|
struct CMempoolAddressDelta |
||||
|
{ |
||||
|
int64_t time; |
||||
|
CAmount amount; |
||||
|
uint256 prevhash; |
||||
|
unsigned int prevout; |
||||
|
|
||||
|
CMempoolAddressDelta(int64_t t, CAmount a, uint256 hash, unsigned int out) { |
||||
|
time = t; |
||||
|
amount = a; |
||||
|
prevhash = hash; |
||||
|
prevout = out; |
||||
|
} |
||||
|
|
||||
|
CMempoolAddressDelta(int64_t t, CAmount a) { |
||||
|
time = t; |
||||
|
amount = a; |
||||
|
prevhash.SetNull(); |
||||
|
prevout = 0; |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
struct CMempoolAddressDeltaKey |
||||
|
{ |
||||
|
int type; |
||||
|
uint160 addressBytes; |
||||
|
uint256 txhash; |
||||
|
unsigned int index; |
||||
|
int spending; |
||||
|
|
||||
|
CMempoolAddressDeltaKey(int addressType, uint160 addressHash, uint256 hash, unsigned int i, int s) { |
||||
|
type = addressType; |
||||
|
addressBytes = addressHash; |
||||
|
txhash = hash; |
||||
|
index = i; |
||||
|
spending = s; |
||||
|
} |
||||
|
|
||||
|
CMempoolAddressDeltaKey(int addressType, uint160 addressHash) { |
||||
|
type = addressType; |
||||
|
addressBytes = addressHash; |
||||
|
txhash.SetNull(); |
||||
|
index = 0; |
||||
|
spending = 0; |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
struct CMempoolAddressDeltaKeyCompare |
||||
|
{ |
||||
|
bool operator()(const CMempoolAddressDeltaKey& a, const CMempoolAddressDeltaKey& b) const { |
||||
|
if (a.type == b.type) { |
||||
|
if (a.addressBytes == b.addressBytes) { |
||||
|
if (a.txhash == b.txhash) { |
||||
|
if (a.index == b.index) { |
||||
|
return a.spending < b.spending; |
||||
|
} else { |
||||
|
return a.index < b.index; |
||||
|
} |
||||
|
} else { |
||||
|
return a.txhash < b.txhash; |
||||
|
} |
||||
|
} else { |
||||
|
return a.addressBytes < b.addressBytes; |
||||
|
} |
||||
|
} else { |
||||
|
return a.type < b.type; |
||||
|
} |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
#endif // BITCOIN_ADDRESSINDEX_H
|
@ -0,0 +1,98 @@ |
|||||
|
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
|
// Copyright (c) 2009-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.
|
||||
|
|
||||
|
#ifndef BITCOIN_SPENTINDEX_H |
||||
|
#define BITCOIN_SPENTINDEX_H |
||||
|
|
||||
|
#include "uint256.h" |
||||
|
#include "amount.h" |
||||
|
|
||||
|
struct CSpentIndexKey { |
||||
|
uint256 txid; |
||||
|
unsigned int outputIndex; |
||||
|
|
||||
|
ADD_SERIALIZE_METHODS; |
||||
|
|
||||
|
template <typename Stream, typename Operation> |
||||
|
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { |
||||
|
READWRITE(txid); |
||||
|
READWRITE(outputIndex); |
||||
|
} |
||||
|
|
||||
|
CSpentIndexKey(uint256 t, unsigned int i) { |
||||
|
txid = t; |
||||
|
outputIndex = i; |
||||
|
} |
||||
|
|
||||
|
CSpentIndexKey() { |
||||
|
SetNull(); |
||||
|
} |
||||
|
|
||||
|
void SetNull() { |
||||
|
txid.SetNull(); |
||||
|
outputIndex = 0; |
||||
|
} |
||||
|
|
||||
|
}; |
||||
|
|
||||
|
struct CSpentIndexValue { |
||||
|
uint256 txid; |
||||
|
unsigned int inputIndex; |
||||
|
int blockHeight; |
||||
|
CAmount satoshis; |
||||
|
int addressType; |
||||
|
uint160 addressHash; |
||||
|
|
||||
|
ADD_SERIALIZE_METHODS; |
||||
|
|
||||
|
template <typename Stream, typename Operation> |
||||
|
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { |
||||
|
READWRITE(txid); |
||||
|
READWRITE(inputIndex); |
||||
|
READWRITE(blockHeight); |
||||
|
READWRITE(satoshis); |
||||
|
READWRITE(addressType); |
||||
|
READWRITE(addressHash); |
||||
|
} |
||||
|
|
||||
|
CSpentIndexValue(uint256 t, unsigned int i, int h, CAmount s, int type, uint160 a) { |
||||
|
txid = t; |
||||
|
inputIndex = i; |
||||
|
blockHeight = h; |
||||
|
satoshis = s; |
||||
|
addressType = type; |
||||
|
addressHash = a; |
||||
|
} |
||||
|
|
||||
|
CSpentIndexValue() { |
||||
|
SetNull(); |
||||
|
} |
||||
|
|
||||
|
void SetNull() { |
||||
|
txid.SetNull(); |
||||
|
inputIndex = 0; |
||||
|
blockHeight = 0; |
||||
|
satoshis = 0; |
||||
|
addressType = 0; |
||||
|
addressHash.SetNull(); |
||||
|
} |
||||
|
|
||||
|
bool IsNull() const { |
||||
|
return txid.IsNull(); |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
struct CSpentIndexKeyCompare |
||||
|
{ |
||||
|
bool operator()(const CSpentIndexKey& a, const CSpentIndexKey& b) const { |
||||
|
if (a.txid == b.txid) { |
||||
|
return a.outputIndex < b.outputIndex; |
||||
|
} else { |
||||
|
return a.txid < b.txid; |
||||
|
} |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
#endif // BITCOIN_SPENTINDEX_H
|
Binary file not shown.
@ -0,0 +1,59 @@ |
|||||
|
// Copyright (c) 2012-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.
|
||||
|
|
||||
|
#include "script/script.h" |
||||
|
#include "test/test_bitcoin.h" |
||||
|
|
||||
|
#include <boost/test/unit_test.hpp> |
||||
|
|
||||
|
using namespace std; |
||||
|
|
||||
|
BOOST_FIXTURE_TEST_SUITE(script_P2PKH_tests, BasicTestingSetup) |
||||
|
|
||||
|
BOOST_AUTO_TEST_CASE(IsPayToPublicKeyHash) |
||||
|
{ |
||||
|
// Test CScript::IsPayToPublicKeyHash()
|
||||
|
uint160 dummy; |
||||
|
CScript p2pkh; |
||||
|
p2pkh << OP_DUP << OP_HASH160 << ToByteVector(dummy) << OP_EQUALVERIFY << OP_CHECKSIG; |
||||
|
BOOST_CHECK(p2pkh.IsPayToPublicKeyHash()); |
||||
|
|
||||
|
static const unsigned char direct[] = { |
||||
|
OP_DUP, OP_HASH160, 20, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, OP_EQUALVERIFY, OP_CHECKSIG |
||||
|
}; |
||||
|
BOOST_CHECK(CScript(direct, direct+sizeof(direct)).IsPayToPublicKeyHash()); |
||||
|
|
||||
|
static const unsigned char notp2pkh1[] = { |
||||
|
OP_DUP, OP_HASH160, 20, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, OP_EQUALVERIFY, OP_CHECKSIG, OP_CHECKSIG |
||||
|
}; |
||||
|
BOOST_CHECK(!CScript(notp2pkh1, notp2pkh1+sizeof(notp2pkh1)).IsPayToPublicKeyHash()); |
||||
|
|
||||
|
static const unsigned char p2sh[] = { |
||||
|
OP_HASH160, 20, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, OP_EQUAL |
||||
|
}; |
||||
|
BOOST_CHECK(!CScript(p2sh, p2sh+sizeof(p2sh)).IsPayToPublicKeyHash()); |
||||
|
|
||||
|
static const unsigned char extra[] = { |
||||
|
OP_DUP, OP_HASH160, 20, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, OP_EQUALVERIFY, OP_CHECKSIG, OP_CHECKSIG |
||||
|
}; |
||||
|
BOOST_CHECK(!CScript(extra, extra+sizeof(extra)).IsPayToPublicKeyHash()); |
||||
|
|
||||
|
static const unsigned char missing[] = { |
||||
|
OP_HASH160, 20, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, OP_EQUALVERIFY, OP_CHECKSIG, OP_RETURN |
||||
|
}; |
||||
|
BOOST_CHECK(!CScript(missing, missing+sizeof(missing)).IsPayToPublicKeyHash()); |
||||
|
|
||||
|
static const unsigned char missing2[] = { |
||||
|
OP_DUP, OP_HASH160, 20, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 |
||||
|
}; |
||||
|
BOOST_CHECK(!CScript(missing2, missing2+sizeof(missing)).IsPayToPublicKeyHash()); |
||||
|
|
||||
|
static const unsigned char tooshort[] = { |
||||
|
OP_DUP, OP_HASH160, 2, 0,0, OP_EQUALVERIFY, OP_CHECKSIG |
||||
|
}; |
||||
|
BOOST_CHECK(!CScript(tooshort, tooshort+sizeof(direct)).IsPayToPublicKeyHash()); |
||||
|
|
||||
|
} |
||||
|
|
||||
|
BOOST_AUTO_TEST_SUITE_END() |
@ -0,0 +1,61 @@ |
|||||
|
#!/usr/bin/python |
||||
|
# Copyright 2014 BitPay, Inc. |
||||
|
# Distributed under the MIT software license, see the accompanying |
||||
|
# file COPYING or http://www.opensource.org/licenses/mit-license.php. |
||||
|
|
||||
|
import subprocess |
||||
|
import os |
||||
|
import json |
||||
|
import sys |
||||
|
import buildenv |
||||
|
import shutil |
||||
|
|
||||
|
def assert_equal(thing1, thing2): |
||||
|
if thing1 != thing2: |
||||
|
raise AssertionError("%s != %s"%(str(thing1),str(thing2))) |
||||
|
|
||||
|
if __name__ == '__main__': |
||||
|
datadir = os.environ["srcdir"] + "/test/data" |
||||
|
execprog = './wallet-utility' + buildenv.exeext |
||||
|
execargs = '-datadir=' + datadir |
||||
|
execrun = execprog + ' ' + execargs |
||||
|
|
||||
|
proc = subprocess.Popen(execrun, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True, shell=True) |
||||
|
try: |
||||
|
outs = proc.communicate() |
||||
|
except OSError: |
||||
|
print("OSError, Failed to execute " + execprog) |
||||
|
sys.exit(1) |
||||
|
|
||||
|
output = json.loads(outs[0]) |
||||
|
|
||||
|
assert_equal(output[0], "13EngsxkRi7SJPPqCyJsKf34U8FoX9E9Av") |
||||
|
assert_equal(output[1], "1FKCLGTpPeYBUqfNxktck8k5nqxB8sjim8") |
||||
|
assert_equal(output[2], "13cdtE9tnNeXCZJ8KQ5WELgEmLSBLnr48F") |
||||
|
|
||||
|
execargs = '-datadir=' + datadir + ' -dumppass' |
||||
|
execrun = execprog + ' ' + execargs |
||||
|
|
||||
|
proc = subprocess.Popen(execrun, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True, shell=True) |
||||
|
try: |
||||
|
outs = proc.communicate() |
||||
|
except OSError: |
||||
|
print("OSError, Failed to execute " + execprog) |
||||
|
sys.exit(1) |
||||
|
|
||||
|
output = json.loads(outs[0]) |
||||
|
|
||||
|
assert_equal(output[0]['addr'], "13EngsxkRi7SJPPqCyJsKf34U8FoX9E9Av") |
||||
|
assert_equal(output[0]['pkey'], "5Jz5BWE2WQxp1hGqDZeisQFV1mRFR2AVBAgiXCbNcZyXNjD9aUd") |
||||
|
assert_equal(output[1]['addr'], "1FKCLGTpPeYBUqfNxktck8k5nqxB8sjim8") |
||||
|
assert_equal(output[1]['pkey'], "5HsX2b3v2GjngYQ5ZM4mLp2b2apw6aMNVaPELV1YmpiYR1S4jzc") |
||||
|
assert_equal(output[2]['addr'], "13cdtE9tnNeXCZJ8KQ5WELgEmLSBLnr48F") |
||||
|
assert_equal(output[2]['pkey'], "5KCWAs1wX2ESiL4PfDR8XYVSSETHFd2jaRGxt1QdanBFTit4XcH") |
||||
|
|
||||
|
if os.path.exists(datadir + '/database'): |
||||
|
if os.path.isdir(datadir + '/database'): |
||||
|
shutil.rmtree(datadir + '/database') |
||||
|
|
||||
|
if os.path.exists(datadir + '/db.log'): |
||||
|
os.remove(datadir + '/db.log') |
||||
|
sys.exit(0) |
@ -0,0 +1,339 @@ |
|||||
|
#include <iostream> |
||||
|
#include <string> |
||||
|
|
||||
|
// Include local headers
|
||||
|
#include "wallet/walletdb.h" |
||||
|
#include "util.h" |
||||
|
#include "base58.h" |
||||
|
#include "wallet/crypter.h" |
||||
|
#include <boost/foreach.hpp> |
||||
|
|
||||
|
|
||||
|
void show_help() |
||||
|
{ |
||||
|
std::cout << |
||||
|
"This program outputs Bitcoin addresses and private keys from a wallet.dat file" << std::endl |
||||
|
<< std::endl |
||||
|
<< "Usage and options: " |
||||
|
<< std::endl |
||||
|
<< " -datadir=<directory> to tell the program where your wallet is" |
||||
|
<< std::endl |
||||
|
<< " -wallet=<name> (Optional) if your wallet is not named wallet.dat" |
||||
|
<< std::endl |
||||
|
<< " -regtest or -testnet (Optional) dumps addresses from regtest/testnet" |
||||
|
<< std::endl |
||||
|
<< " -dumppass (Optional)if you want to extract private keys associated with addresses" |
||||
|
<< std::endl |
||||
|
<< " -pass=<walletpassphrase> if you have encrypted private keys stored in your wallet" |
||||
|
<< std::endl; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
class WalletUtilityDB : public CDB |
||||
|
{ |
||||
|
private: |
||||
|
typedef std::map<unsigned int, CMasterKey> MasterKeyMap; |
||||
|
MasterKeyMap mapMasterKeys; |
||||
|
unsigned int nMasterKeyMaxID; |
||||
|
SecureString mPass; |
||||
|
std::vector<CKeyingMaterial> vMKeys; |
||||
|
|
||||
|
public: |
||||
|
WalletUtilityDB(const std::string& strFilename, const char* pszMode = "r+", bool fFlushOnClose = true) : CDB(strFilename, pszMode, fFlushOnClose) |
||||
|
{ |
||||
|
nMasterKeyMaxID = 0; |
||||
|
mPass.reserve(100); |
||||
|
} |
||||
|
|
||||
|
std::string getAddress(CDataStream ssKey); |
||||
|
std::string getKey(CDataStream ssKey, CDataStream ssValue); |
||||
|
std::string getCryptedKey(CDataStream ssKey, CDataStream ssValue, std::string masterPass); |
||||
|
bool updateMasterKeys(CDataStream ssKey, CDataStream ssValue); |
||||
|
bool parseKeys(bool dumppriv, std::string masterPass); |
||||
|
|
||||
|
bool DecryptSecret(const std::vector<unsigned char>& vchCiphertext, const uint256& nIV, CKeyingMaterial& vchPlaintext); |
||||
|
bool Unlock(); |
||||
|
bool DecryptKey(const std::vector<unsigned char>& vchCryptedSecret, const CPubKey& vchPubKey, CKey& key); |
||||
|
}; |
||||
|
|
||||
|
|
||||
|
/*
|
||||
|
* Address from a public key in base58 |
||||
|
*/ |
||||
|
std::string WalletUtilityDB::getAddress(CDataStream ssKey) |
||||
|
{ |
||||
|
CPubKey vchPubKey; |
||||
|
ssKey >> vchPubKey; |
||||
|
CKeyID id = vchPubKey.GetID(); |
||||
|
std::string strAddr = CBitcoinAddress(id).ToString(); |
||||
|
|
||||
|
return strAddr; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/*
|
||||
|
* Non encrypted private key in WIF |
||||
|
*/ |
||||
|
std::string WalletUtilityDB::getKey(CDataStream ssKey, CDataStream ssValue) |
||||
|
{ |
||||
|
std::string strKey; |
||||
|
CPubKey vchPubKey; |
||||
|
ssKey >> vchPubKey; |
||||
|
CPrivKey pkey; |
||||
|
CKey key; |
||||
|
|
||||
|
ssValue >> pkey; |
||||
|
if (key.Load(pkey, vchPubKey, true)) |
||||
|
strKey = CBitcoinSecret(key).ToString(); |
||||
|
|
||||
|
return strKey; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
bool WalletUtilityDB::DecryptSecret(const std::vector<unsigned char>& vchCiphertext, const uint256& nIV, CKeyingMaterial& vchPlaintext) |
||||
|
{ |
||||
|
CCrypter cKeyCrypter; |
||||
|
std::vector<unsigned char> chIV(WALLET_CRYPTO_KEY_SIZE); |
||||
|
memcpy(&chIV[0], &nIV, WALLET_CRYPTO_KEY_SIZE); |
||||
|
|
||||
|
BOOST_FOREACH(const CKeyingMaterial vMKey, vMKeys) |
||||
|
{ |
||||
|
if(!cKeyCrypter.SetKey(vMKey, chIV)) |
||||
|
continue; |
||||
|
if (cKeyCrypter.Decrypt(vchCiphertext, *((CKeyingMaterial*)&vchPlaintext))) |
||||
|
return true; |
||||
|
} |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
bool WalletUtilityDB::Unlock() |
||||
|
{ |
||||
|
CCrypter crypter; |
||||
|
CKeyingMaterial vMasterKey; |
||||
|
|
||||
|
BOOST_FOREACH(const MasterKeyMap::value_type& pMasterKey, mapMasterKeys) |
||||
|
{ |
||||
|
if(!crypter.SetKeyFromPassphrase(mPass, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod)) |
||||
|
return false; |
||||
|
if (!crypter.Decrypt(pMasterKey.second.vchCryptedKey, vMasterKey)) |
||||
|
continue; // try another master key
|
||||
|
vMKeys.push_back(vMasterKey); |
||||
|
} |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
bool WalletUtilityDB::DecryptKey(const std::vector<unsigned char>& vchCryptedSecret, const CPubKey& vchPubKey, CKey& key) |
||||
|
{ |
||||
|
CKeyingMaterial vchSecret; |
||||
|
if(!DecryptSecret(vchCryptedSecret, vchPubKey.GetHash(), vchSecret)) |
||||
|
return false; |
||||
|
|
||||
|
if (vchSecret.size() != 32) |
||||
|
return false; |
||||
|
|
||||
|
key.Set(vchSecret.begin(), vchSecret.end(), vchPubKey.IsCompressed()); |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/*
|
||||
|
* Encrypted private key in WIF format |
||||
|
*/ |
||||
|
std::string WalletUtilityDB::getCryptedKey(CDataStream ssKey, CDataStream ssValue, std::string masterPass) |
||||
|
{ |
||||
|
mPass = masterPass.c_str(); |
||||
|
CPubKey vchPubKey; |
||||
|
ssKey >> vchPubKey; |
||||
|
CKey key; |
||||
|
|
||||
|
std::vector<unsigned char> vKey; |
||||
|
ssValue >> vKey; |
||||
|
|
||||
|
if (!Unlock()) |
||||
|
return ""; |
||||
|
|
||||
|
if(!DecryptKey(vKey, vchPubKey, key)) |
||||
|
return ""; |
||||
|
|
||||
|
std::string strKey = CBitcoinSecret(key).ToString(); |
||||
|
return strKey; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/*
|
||||
|
* Master key derivation |
||||
|
*/ |
||||
|
bool WalletUtilityDB::updateMasterKeys(CDataStream ssKey, CDataStream ssValue) |
||||
|
{ |
||||
|
unsigned int nID; |
||||
|
ssKey >> nID; |
||||
|
CMasterKey kMasterKey; |
||||
|
ssValue >> kMasterKey; |
||||
|
if (mapMasterKeys.count(nID) != 0) |
||||
|
{ |
||||
|
std::cout << "Error reading wallet database: duplicate CMasterKey id " << nID << std::endl; |
||||
|
return false; |
||||
|
} |
||||
|
mapMasterKeys[nID] = kMasterKey; |
||||
|
|
||||
|
if (nMasterKeyMaxID < nID) |
||||
|
nMasterKeyMaxID = nID; |
||||
|
|
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/*
|
||||
|
* Look at all the records and parse keys for addresses and private keys |
||||
|
*/ |
||||
|
bool WalletUtilityDB::parseKeys(bool dumppriv, std::string masterPass) |
||||
|
{ |
||||
|
DBErrors result = DB_LOAD_OK; |
||||
|
std::string strType; |
||||
|
bool first = true; |
||||
|
|
||||
|
try { |
||||
|
Dbc* pcursor = GetCursor(); |
||||
|
if (!pcursor) |
||||
|
{ |
||||
|
LogPrintf("Error getting wallet database cursor\n"); |
||||
|
result = DB_CORRUPT; |
||||
|
} |
||||
|
|
||||
|
if (dumppriv) |
||||
|
{ |
||||
|
while (result == DB_LOAD_OK && true) |
||||
|
{ |
||||
|
CDataStream ssKey(SER_DISK, CLIENT_VERSION); |
||||
|
CDataStream ssValue(SER_DISK, CLIENT_VERSION); |
||||
|
int result = ReadAtCursor(pcursor, ssKey, ssValue); |
||||
|
|
||||
|
if (result == DB_NOTFOUND) { |
||||
|
break; |
||||
|
} |
||||
|
else if (result != 0) |
||||
|
{ |
||||
|
LogPrintf("Error reading next record from wallet database\n"); |
||||
|
result = DB_CORRUPT; |
||||
|
break; |
||||
|
} |
||||
|
|
||||
|
ssKey >> strType; |
||||
|
if (strType == "mkey") |
||||
|
{ |
||||
|
updateMasterKeys(ssKey, ssValue); |
||||
|
} |
||||
|
} |
||||
|
pcursor->close(); |
||||
|
pcursor = GetCursor(); |
||||
|
} |
||||
|
|
||||
|
while (result == DB_LOAD_OK && true) |
||||
|
{ |
||||
|
CDataStream ssKey(SER_DISK, CLIENT_VERSION); |
||||
|
CDataStream ssValue(SER_DISK, CLIENT_VERSION); |
||||
|
int ret = ReadAtCursor(pcursor, ssKey, ssValue); |
||||
|
|
||||
|
if (ret == DB_NOTFOUND) |
||||
|
{ |
||||
|
std::cout << " ]" << std::endl; |
||||
|
first = true; |
||||
|
break; |
||||
|
} |
||||
|
else if (ret != DB_LOAD_OK) |
||||
|
{ |
||||
|
LogPrintf("Error reading next record from wallet database\n"); |
||||
|
result = DB_CORRUPT; |
||||
|
break; |
||||
|
} |
||||
|
|
||||
|
ssKey >> strType; |
||||
|
|
||||
|
if (strType == "key" || strType == "ckey") |
||||
|
{ |
||||
|
std::string strAddr = getAddress(ssKey); |
||||
|
std::string strKey = ""; |
||||
|
|
||||
|
|
||||
|
if (dumppriv && strType == "key") |
||||
|
strKey = getKey(ssKey, ssValue); |
||||
|
if (dumppriv && strType == "ckey") |
||||
|
{ |
||||
|
if (masterPass == "") |
||||
|
{ |
||||
|
std::cout << "Encrypted wallet, please provide a password. See help below" << std::endl; |
||||
|
show_help(); |
||||
|
result = DB_LOAD_FAIL; |
||||
|
break; |
||||
|
} |
||||
|
strKey = getCryptedKey(ssKey, ssValue, masterPass); |
||||
|
} |
||||
|
|
||||
|
if (strAddr != "") |
||||
|
{ |
||||
|
if (first) |
||||
|
std::cout << "[ "; |
||||
|
else |
||||
|
std::cout << ", "; |
||||
|
} |
||||
|
|
||||
|
if (dumppriv) |
||||
|
{ |
||||
|
std::cout << "{\"addr\" : \"" + strAddr + "\", " |
||||
|
<< "\"pkey\" : \"" + strKey + "\"}" |
||||
|
<< std::flush; |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
std::cout << "\"" + strAddr + "\""; |
||||
|
} |
||||
|
|
||||
|
first = false; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
pcursor->close(); |
||||
|
} catch (DbException &e) { |
||||
|
std::cout << "DBException caught " << e.get_errno() << std::endl; |
||||
|
} catch (std::exception &e) { |
||||
|
std::cout << "Exception caught " << std::endl; |
||||
|
} |
||||
|
|
||||
|
if (result == DB_LOAD_OK) |
||||
|
return true; |
||||
|
else |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
int main(int argc, char* argv[]) |
||||
|
{ |
||||
|
ParseParameters(argc, argv); |
||||
|
std::string walletFile = GetArg("-wallet", "wallet.dat"); |
||||
|
std::string masterPass = GetArg("-pass", ""); |
||||
|
bool fDumpPass = GetBoolArg("-dumppass", false); |
||||
|
bool help = GetBoolArg("-h", false); |
||||
|
bool result = false; |
||||
|
|
||||
|
if (help) |
||||
|
{ |
||||
|
show_help(); |
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
try { |
||||
|
SelectParamsFromCommandLine(); |
||||
|
result = WalletUtilityDB(walletFile, "r").parseKeys(fDumpPass, masterPass); |
||||
|
} |
||||
|
catch (const std::exception& e) { |
||||
|
std::cout << "Error opening wallet file " << walletFile << std::endl; |
||||
|
std::cout << e.what() << std::endl; |
||||
|
} |
||||
|
|
||||
|
if (result) |
||||
|
return 0; |
||||
|
else |
||||
|
return -1; |
||||
|
} |
Loading…
Reference in new issue