![martindube@martindube.com](/assets/img/avatar_default.png)
committed by
GitHub
![GitHub](/assets/img/avatar_default.png)
136 changed files with 5688 additions and 228 deletions
@ -1,47 +0,0 @@ |
|||
zcash (1.0.3) jessie; urgency=medium |
|||
|
|||
* 1.0.3 release. |
|||
|
|||
-- Zcash Company <team@z.cash> Wed, 17 Nov 2016 15:56:00 -0700 |
|||
|
|||
zcash (1.0.2) jessie; urgency=medium |
|||
|
|||
* 1.0.2 release. |
|||
|
|||
-- Zcash Company <team@z.cash> Mon, 07 Nov 2016 19:01:35 -0600 |
|||
|
|||
zcash (1.0.1) jessie; urgency=medium |
|||
|
|||
* 1.0.1 release. |
|||
|
|||
-- Zcash Company <team@z.cash> Thu, 03 Nov 2016 23:21:09 -0500 |
|||
|
|||
zcash (1.0.0-sprout) jessie; urgency=medium |
|||
|
|||
* 1.0.0 release. |
|||
|
|||
-- Zcash Company <team@z.cash> Fri, 28 Oct 2016 03:00:50 -0700 |
|||
|
|||
zcash (1.0.0-rc4) jessie; urgency=medium |
|||
|
|||
* 1.0.0-rc4 release. |
|||
|
|||
-- Zcash Company <team@z.cash> Thu, 27 Oct 2016 13:36:00 +0100 |
|||
|
|||
zcash (1.0.0-rc3) jessie; urgency=medium |
|||
|
|||
* 1.0.0-rc3 release. |
|||
|
|||
-- Zcash Company <team@z.cash> Wed, 26 Oct 2016 23:17:03 +0100 |
|||
|
|||
zcash (1.0.0-rc2) jessie; urgency=medium |
|||
|
|||
* 1.0.0-rc2 release. |
|||
|
|||
-- Zcash Company <team@z.cash> Sun, 23 Oct 2016 01:51:27 +0100 |
|||
|
|||
zcash (1.0.0-rc1) jessie; urgency=medium |
|||
|
|||
* Initial packaging for Debian. |
|||
|
|||
-- Zcash Company <team@z.cash> Mon, 17 Oct 2016 11:47:02 -0700 |
@ -1 +1 @@ |
|||
# mainnet nodes |
|||
# mainnet nodes |
@ -1,2 +1,3 @@ |
|||
# 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 |
|||
|
|||
|
@ -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,94 @@ |
|||
# Shielding Coinbase UTXOs |
|||
|
|||
**Summary** |
|||
|
|||
Use `z_shieldcoinbase` RPC call to shield coinbase UTXOs. |
|||
|
|||
**Who should read this document** |
|||
|
|||
Miners, Mining pools, Online wallets |
|||
|
|||
## Background |
|||
|
|||
The current Zcash protocol includes a consensus rule that coinbase rewards must be sent to a shielded address |
|||
and the Hush network follows this consensus rule. |
|||
|
|||
## User Experience Challenges |
|||
|
|||
A user can use the z_sendmany RPC call to shield coinbase funds, but the call was not designed for sweeping up many UTXOs, and offered a suboptimal user experience. |
|||
|
|||
If customers send mining pool payouts to their online wallet, the service provider must sort through UTXOs to correctly determine the non-coinbase UTXO funds that can be withdrawn or transferred by customers to another transparent address. |
|||
|
|||
## Solution |
|||
|
|||
The z_shieldcoinbase call makes it easy to sweep up coinbase rewards from multiple coinbase UTXOs across multiple coinbase reward addresses. |
|||
|
|||
z_shieldcoinbase fromaddress toaddress (fee) (limit) |
|||
|
|||
The default fee is 0.0010000 HUSH and the default limit on the maximum number of UTXOs to shield is 50. |
|||
|
|||
## Examples |
|||
|
|||
Sweep up coinbase UTXOs from a transparent address you use for mining: |
|||
|
|||
hush-cli z_shieldcoinbase tMyMiningAddress zMyPrivateAddress |
|||
|
|||
Sweep up coinbase UTXOs from multiple transparent addresses to a shielded address: |
|||
|
|||
hush-cli z_shieldcoinbase "*" zMyPrivateAddress |
|||
|
|||
Sweep up with a fee of 1.23 HUSH: |
|||
|
|||
hush-cli z_shieldcoinbase tMyMiningAddress zMyPrivateAddress 1.23 |
|||
|
|||
Sweep up with a fee of 0.1 HUSH and set limit on the maximum number of UTXOs to shield at 25: |
|||
|
|||
hush-cli z_shieldcoinbase "*" zMyPrivateAddress 0.1 25 |
|||
|
|||
### Asynchronous Call |
|||
|
|||
The `z_shieldcoinbase` RPC call is an asynchronous call, so you can queue up multiple operations. |
|||
|
|||
When you invoke |
|||
|
|||
hush-cli z_shieldcoinbase tMyMiningAddress zMyPrivateAddress |
|||
|
|||
JSON will be returned immediately, with the following data fields populated: |
|||
|
|||
- operationid: a temporary id to use with `z_getoperationstatus` and `z_getoperationresult` to get the status and result of the operation. |
|||
- shieldedUTXOs: number of coinbase UTXOs being shielded |
|||
- shieldedValue: value of coinbase UTXOs being shielded. |
|||
- remainingUTXOs: number of coinbase UTXOs still available for shielding. |
|||
- remainingValue: value of coinbase UTXOs still available for shielding |
|||
|
|||
### Locking UTXOs |
|||
|
|||
The `z_shieldcoinbase` call will lock any selected UTXOs. This prevents the selected UTXOs which are already queued up from being selected for any other send operation. If the `z_shieldcoinbase` call fails, any locked UTXOs are unlocked. |
|||
|
|||
You can use the RPC call `lockunspent` to see which UTXOs have been locked. You can also use this call to unlock any UTXOs in the event of an unexpected system failure which leaves UTXOs in a locked state. |
|||
|
|||
### Limits, Performance and Transaction Confirmation |
|||
|
|||
The number of coinbase UTXOs selected for shielding can be adjusted by setting the limit parameter. The default value is 50. |
|||
|
|||
If the limit parameter is set to zero, the hushd `mempooltxinputlimit` option will be used instead, where the default value for `mempooltxinputlimit` is zero, which means no limit. |
|||
|
|||
Any limit is constrained by a hard limit due to the consensus rule defining a maximum transaction size of 100,000 bytes. |
|||
|
|||
In general, the more UTXOs that are selected, the longer it takes for the transaction to be verified. Due to the quadratic hashing problem, some miners use the `mempooltxinputlimit` option to reject transactions with a large number of UTXO inputs. |
|||
|
|||
Currently, as of November 2017, there is no commonly agreed upon limit, but as a rule of thumb (a form of emergent consensus) if a transaction has less than 100 UTXO inputs, the transaction will be mined promptly by the majority of mining pools, but if it has many more UTXO inputs, such as 500, it might take several days to be mined by a miner who has higher or no limits. |
|||
|
|||
### Anatomy of a z_shieldcoinbase transaction |
|||
|
|||
The transaction created is a shielded transaction. It consists of a single joinsplit, which consumes coinbase UTXOs as input, and deposits value at a shielded address, minus any fee. |
|||
|
|||
The number of coinbase UTXOs is determined by a user configured limit. |
|||
|
|||
If no limit is set (in the case when limit parameter and `mempooltxinputlimit` options are set to zero) the behaviour of z_shieldcoinbase is to consume as many UTXOs as possible, with `z_shieldcoinbase` constructing a transaction up to the size limit of 100,000 bytes. |
|||
|
|||
As a result, the maximum number of inputs that can be selected is: |
|||
|
|||
- P2PKH coinbase UTXOs ~ 662 |
|||
- 2-of-3 multisig P2SH coinbase UTXOs ~ 244. |
|||
|
@ -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) |
@ -0,0 +1,12 @@ |
|||
Release notes for Hush 1.0.13 |
|||
|
|||
- Includes all bug fixes from zcash 1.0.13 (upstream) |
|||
- Fixes network sync issue. |
|||
- Adds new DNS seed nodes help nodes connect and find other nodes faster. |
|||
- Implements TLS options - allows options for self-signed or CA-signed TLS. Options can also be set to require TLS and/or CA-signed certs. |
|||
- TLS options have been tested and work on Windows, Mac, and Linux. |
|||
- TLS setup instructions are at: https://github.com/MyHush/hush/blob/master/SECURE_SETUP.md |
|||
- Large memory reduction when processing shielded transactions. |
|||
- Enabled new RPC methods from zcash upstream: z-shieldcoinbase z_getpaymentdisclosure z_validatepaymentdisclosure. |
|||
- Adds ability to compile on Mac (experimental). |
|||
- Hush continues to be supported by BarterDEX and the Agama Wallet. |
@ -1,15 +1,15 @@ |
|||
bitcoin ICON "pixmaps/bitcoin.ico" |
|||
|
|||
#include "wx/msw/wx.rc" |
|||
|
|||
check ICON "pixmaps/check.ico" |
|||
send16 BITMAP "pixmaps/send16.bmp" |
|||
send16mask BITMAP "pixmaps/send16mask.bmp" |
|||
send16masknoshadow BITMAP "pixmaps/send16masknoshadow.bmp" |
|||
send20 BITMAP "pixmaps/send20.bmp" |
|||
send20mask BITMAP "pixmaps/send20mask.bmp" |
|||
addressbook16 BITMAP "pixmaps/addressbook16.bmp" |
|||
addressbook16mask BITMAP "pixmaps/addressbook16mask.bmp" |
|||
addressbook20 BITMAP "pixmaps/addressbook20.bmp" |
|||
addressbook20mask BITMAP "pixmaps/addressbook20mask.bmp" |
|||
favicon ICON "pixmaps/favicon.ico" |
|||
bitcoin ICON "pixmaps/bitcoin.ico" |
|||
|
|||
#include "wx/msw/wx.rc" |
|||
|
|||
check ICON "pixmaps/check.ico" |
|||
send16 BITMAP "pixmaps/send16.bmp" |
|||
send16mask BITMAP "pixmaps/send16mask.bmp" |
|||
send16masknoshadow BITMAP "pixmaps/send16masknoshadow.bmp" |
|||
send20 BITMAP "pixmaps/send20.bmp" |
|||
send20mask BITMAP "pixmaps/send20mask.bmp" |
|||
addressbook16 BITMAP "pixmaps/addressbook16.bmp" |
|||
addressbook16mask BITMAP "pixmaps/addressbook16mask.bmp" |
|||
addressbook20 BITMAP "pixmaps/addressbook20.bmp" |
|||
addressbook20mask BITMAP "pixmaps/addressbook20mask.bmp" |
|||
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; |
|||
} |
@ -0,0 +1,72 @@ |
|||
#!/bin/bash |
|||
export CC=gcc-5 |
|||
export CXX=g++-5 |
|||
export LIBTOOL=libtool |
|||
export AR=ar |
|||
export RANLIB=ranlib |
|||
export STRIP=strip |
|||
export OTOOL=otool |
|||
export NM=nm |
|||
|
|||
set -eu -o pipefail |
|||
|
|||
if [ "x$*" = 'x--help' ] |
|||
then |
|||
cat <<EOF |
|||
Usage: |
|||
$0 --help |
|||
Show this help message and exit. |
|||
$0 [ --enable-lcov ] [ MAKEARGS... ] |
|||
Build Hush and most of its transitive dependencies from |
|||
source. MAKEARGS are applied to both dependencies and Hush itself. If |
|||
--enable-lcov is passed, Hush is configured to add coverage |
|||
instrumentation, thus enabling "make cov" to work. |
|||
EOF |
|||
exit 0 |
|||
fi |
|||
|
|||
# If --enable-lcov is the first argument, enable lcov coverage support: |
|||
LCOV_ARG='' |
|||
HARDENING_ARG='--disable-hardening' |
|||
if [ "x${1:-}" = 'x--enable-lcov' ] |
|||
then |
|||
LCOV_ARG='--enable-lcov' |
|||
HARDENING_ARG='--disable-hardening' |
|||
shift |
|||
fi |
|||
|
|||
# If --disable-mining is the next argument, disable mining code: |
|||
MINING_ARG='' |
|||
if [ "x${1:-}" = 'x--disable-mining' ] |
|||
then |
|||
MINING_ARG='--enable-mining=no' |
|||
shift |
|||
fi |
|||
|
|||
# If --disable-rust is the next argument, disable Rust code: |
|||
RUST_ARG='' |
|||
if [ "x${1:-}" = 'x--disable-rust' ] |
|||
then |
|||
RUST_ARG='--enable-rust=no' |
|||
shift |
|||
fi |
|||
|
|||
# If --enable-proton is the next argument, enable building Proton code: |
|||
PROTON_ARG='--enable-proton=no' |
|||
if [ "x${1:-}" = 'x--enable-proton' ] |
|||
then |
|||
PROTON_ARG='' |
|||
shift |
|||
fi |
|||
|
|||
TRIPLET=`./depends/config.guess` |
|||
PREFIX="$(pwd)/depends/$TRIPLET" |
|||
|
|||
NO_RUST="$RUST_ARG" NO_PROTON="$PROTON_ARG" make "$@" -C ./depends/ V=1 NO_QT=1 |
|||
|
|||
./autogen.sh |
|||
CPPFLAGS="-I$PREFIX/include -arch x86_64" LDFLAGS="-L$PREFIX/lib -arch x86_64 -Wl,-no_pie" \ |
|||
CXXFLAGS='-arch x86_64 -I/usr/local/Cellar/gcc5/5.4.0/include/c++/5.4.0 -I$PREFIX/include -fwrapv -fno-strict-aliasing -Werror -g -Wl,-undefined -Wl,dynamic_lookup' \ |
|||
./configure --prefix="${PREFIX}" --with-gui=no "$HARDENING_ARG" "$LCOV_ARG" "$RUST_ARG" "$PROTON_ARG" "$MINING_ARG" |
|||
|
|||
make "$@" V=1 NO_GTEST=0 STATIC=1 |
Loading…
Reference in new issue