From 9e632ac7a04d83a440915c1287576b323c88d587 Mon Sep 17 00:00:00 2001 From: Aezora <59030118+Aezora@users.noreply.github.com> Date: Sun, 31 May 2020 17:52:40 +0800 Subject: [PATCH] v1.1.1 --- CMakeLists.txt | 2 +- configure.ac | 2 +- doc/release-notes.md | 361 +------------ share/genbuild.sh | 2 +- src/Makefile.am | 4 +- src/Makefile.test.include | 23 +- src/addrman.h | 10 +- src/aezora-tx.cpp | 17 +- src/amount.h | 2 +- src/arith_uint256.h | 9 +- src/base58.h | 4 +- src/blob_uint256.h | 9 +- src/bloom.h | 2 +- src/chain.h | 14 +- src/chainparams.cpp | 2 +- src/coins.h | 47 +- src/compressor.h | 15 +- src/consensus/zerocoin_verify.cpp | 2 +- src/core_io.h | 5 +- src/core_write.cpp | 67 ++- src/crypter.h | 2 +- src/{leveldbwrapper.cpp => dbwrapper.cpp} | 61 ++- src/{leveldbwrapper.h => dbwrapper.h} | 135 ++++- src/hash.h | 13 +- src/init.cpp | 2 +- src/key.cpp | 6 +- src/libzerocoin/Accumulator.h | 2 +- src/libzerocoin/Coin.h | 4 +- .../CoinRandomnessSchnorrSignature.h | 2 +- src/libzerocoin/CoinSpend.h | 8 +- src/libzerocoin/Commitment.h | 2 +- src/libzerocoin/Params.h | 6 +- src/libzerocoin/bignum.h | 13 +- src/main.cpp | 26 +- src/masternode-budget.cpp | 14 +- src/masternode-budget.h | 16 +- src/masternode-payments.cpp | 2 +- src/masternode-payments.h | 10 +- src/masternode.cpp | 78 ++- src/masternode.h | 12 +- src/masternodeman.h | 2 +- src/merkleblock.h | 4 +- src/net.cpp | 108 ++-- src/net.h | 14 +- src/netbase.cpp | 8 +- src/netbase.h | 6 +- src/primitives/block.h | 12 +- src/primitives/transaction.cpp | 4 +- src/primitives/transaction.h | 18 +- src/protocol.h | 13 +- src/pubkey.cpp | 4 +- src/pubkey.h | 8 +- src/qt/recentrequeststablemodel.h | 5 +- src/qt/walletmodel.h | 3 +- src/rest.cpp | 2 +- src/rpc/blockchain.cpp | 4 +- src/rpc/net.cpp | 88 +--- src/rpc/rawtransaction.cpp | 6 +- src/script/bitcoinconsensus.cpp | 10 +- src/script/interpreter.cpp | 32 +- src/script/interpreter.h | 2 + src/script/keyorigin.h | 2 +- src/script/script.cpp | 39 -- src/script/script.h | 1 - src/serialize.h | 448 +++++++--------- src/spork.h | 4 +- src/sporkdb.cpp | 2 +- src/sporkdb.h | 4 +- src/streams.h | 94 ++-- src/swifttx.h | 2 +- src/test/benchmark_zerocoin.cpp | 414 --------------- src/test/dbwrapper_tests.cpp | 117 +++++ src/test/libzerocoin_tests.cpp | 493 ------------------ src/test/net_tests.cpp | 147 ++++++ src/test/prevector_tests.cpp | 242 +++++++++ src/test/rpc_wallet_tests.cpp | 185 ------- src/test/sync_tests.cpp | 52 ++ src/txdb.cpp | 199 +++---- src/txdb.h | 10 +- src/undo.h | 27 +- src/version.h | 6 +- src/wallet/hdchain.h | 4 +- src/wallet/rpcwallet.cpp | 2 +- src/wallet/wallet.cpp | 4 +- src/wallet/wallet.h | 29 +- src/wallet/wallet_zerocoin.cpp | 2 +- src/wallet/walletdb.h | 4 +- src/zazr/deterministicmint.h | 4 +- src/zazr/zazrmodule.h | 3 +- src/zazr/zazrwallet.cpp | 2 +- src/zazr/zerocoin.h | 4 +- 91 files changed, 1477 insertions(+), 2435 deletions(-) rename src/{leveldbwrapper.cpp => dbwrapper.cpp} (68%) rename src/{leveldbwrapper.h => dbwrapper.h} (53%) delete mode 100644 src/test/benchmark_zerocoin.cpp create mode 100644 src/test/dbwrapper_tests.cpp delete mode 100644 src/test/libzerocoin_tests.cpp create mode 100644 src/test/net_tests.cpp create mode 100644 src/test/prevector_tests.cpp delete mode 100644 src/test/rpc_wallet_tests.cpp create mode 100644 src/test/sync_tests.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 13d4a90d0..955c22482 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -295,7 +295,7 @@ set(SERVER_SOURCES ./src/httprpc.cpp ./src/httpserver.cpp ./src/init.cpp - ./src/leveldbwrapper.cpp + ./src/dbwrapper.cpp ./src/main.cpp ./src/merkleblock.cpp ./src/miner.cpp diff --git a/configure.ac b/configure.ac index e601c16a0..a14185c4c 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ dnl require autoconf 2.60 (AS_ECHO/AS_ECHO_N) AC_PREREQ([2.60]) define(_CLIENT_VERSION_MAJOR, 1) define(_CLIENT_VERSION_MINOR, 1) -define(_CLIENT_VERSION_REVISION, 0) +define(_CLIENT_VERSION_REVISION, 1) define(_CLIENT_VERSION_BUILD, 0) define(_CLIENT_VERSION_RC, 0) define(_CLIENT_VERSION_IS_RELEASE, true) diff --git a/doc/release-notes.md b/doc/release-notes.md index aa26548f3..874a127db 100644 --- a/doc/release-notes.md +++ b/doc/release-notes.md @@ -34,361 +34,52 @@ Notable Changes (Developers: add your notes here as part of your pull requests whenever possible) -New Wallet UI -------------------- - -v4.0.0 introduces a completely new GUI for the wallet, designed and coded from the ground up by the [Krubit](https://krubit.com/) team. - -This new UI, aside from the overall design large implementation, includes user-focused improvements and features such as a brief introduction on first load, a FAQ section, one-click QRCode compatible receiving addresses, masternode creation wizard, dark and light themes, filterable staking charts, and much more. - -You can read more details about this extensive work in ([PR #954](https://github.com/Aezora/AEZORA/pull/954)) - -There are some legacy features that have not been included, however, notably the in-wallet block explorer and the governance page. The in-wallet block explorer was sorely outdated, and the governance page was a newer addition that will be seeing a return in a future version. - -Cold Staking -------------------- - -A brand new feature is being introduced with the release of v4.0.0: Cold Staking ([PR #955](https://github.com/Aezora/AEZORA/pull/955))! This feature allows a coin owner to keep coins in a "cold" (or locked) wallet whilst a "hot" wallet carries out the burden of staking those coins. - -This brings added security to coin owners as they are no longer required to use an unlocked or partially unlocked wallet (with the ability to spend coins anywhere) in order to gain staking rewards. Users who have chosen to store their coins on hardware devices such as a Ledger or Trezor1 can also gain staking rewards with those coins. - -A full technical writup is available on the [AEZORA Wiki](https://github.com/Aezora/AEZORA/wiki/ColdStaking), and an initial video showcase is available on [YouTube](https://www.youtube.com/watch?v=utxB5TzAeXc). -A brief guide to setup cold staking with GUI and RPC is available [here](https://github.com/random-zebra/AEZORA-Wiki/blob/master/User-Documentation/Cold-Staking-HowTo.md). - -1 Spending cold stakes from HW wallets currently available only for Ledger devices via [PET4L](https://github.com/Aezora/PET4L) tool. - -Multi-Split Stake Splitting -------------------- - -Stake splitting has received a makeover and now supports splitting to more than two (2) outputs. [PR #968](https://github.com/Aezora/AEZORA/pull/968) introduced the change, which is controlled by the wallet's `stakesplitthreshold` setting. - -The default split threshold remains at 2000 AZR, and can be adjusted in the GUI's Settings page, or via the RPC `setstakesplitthreshold` command. - -For a real example, with a stake split threshold of 1500, and a UTXO of 4708.1557; the current stake split algorithm would break that into two outputs of approximately 2355.07785. With this new logic; it will be broken into 3 outputs instead of two; each sized 1570.0519 (4708.1557 input + 2 stake = 4710.1557 / 3 outputs = 1570.0519. - -The maximum number of outputs is currently capped at 48. Also, in relation to the new Cold Staking feature described above; the stake split threshold is set by the staker wallet and **NOT** the owner wallet. - -New Consensus Rules -------------------- - -The following consensus rule changes will be enforced on or shortly after block `2153200`. Note that **Upgrade Enforcement** (mentioned above) will occur prior to this block height. - -### V1 zAZR Spending (Public Spends Version 4) - -Since the discovery of a critical exploit within the libzerocoin library in early 2019, remaining legacy v1 zAZR have been un-spendable. We're happy to say that, once the new consensus rules are in effect, users will once again be able to spend their v1 zAZR with public spends version 4 ([PR #936](https://github.com/Aezora/AEZORA/pull/936)). - -As with the previous version 3 public spends introduced in core wallet version 3.3.0 (enabling the spending of v2 zAZR), version 4 spends will also be public. A full technical writeup is available on the [AEZORA Wiki](https://github.com/Aezora/AEZORA/wiki/CoinRandomnessSchnorrSignature). - -### OP_CHECKCOLDSTAKEVERIFY and P2CS - -Cold staking introduces a new opcode, `OP_CHECKCOLDSTAKEVERIFY`, in the scripting language, and a new standard transaction type using it, named `P2CS` (Pay-To-Cold-Staking). A P2CS script is defined as follows: -``` -OP_DUP OP_HASH160 OP_ROT OP_IF OP_CHECKCOLDSTAKEVERIFY [HASH160(stakerPubKey] -OP_ELSE [HASH160(ownerPubKey)] OP_ENDIF OP_EQUALVERIFY OP_CHECKSIG -``` -`OP_CHECKCOLDSTAKEVERIFY` is used to ensure that the staker can only spend the output in a valid coinstake transaction (using the same P2CS script in the new output). - -### Time Protocol v2 - -[#PR1002](https://github.com/Aezora/AEZORA/pull/1002) introduces a new time protocol for the Proof-Of-Stake consensus mechanism, to ensure better efficiency, fairness and security. The time is now divided in 15-seconds slots and valid blocktimes are at the beginning of each slot (i.e. the block timestamp's seconds can only be `00`, or `15`, or `30` or `45`).
-The maximum future time limit is lowered from 3 minutes to 14 seconds and the past limit is set to the previous blocktime (i.e. a block can no longer have a timestamp earlier than its previous block).
-This means that, when looking for a valid kernel, each stakeable input can be hashed only once every 15 seconds (once per timeslot), and it is not possible to submit blocks with timestamp higher than the current time slot. This ultimately enables the removal of the "hashdrift" concept.
- -**NOTE:** Given the much stricter time constraints, a node's clock synchronization is required for P2P connections: the maximum time offset is 15 seconds and peers with a time drift higher than 30 seconds (in absolute value) will be outright disconnected. - - For advanced users, we recommend the setup of NTP clients and own servers. This will provide to your node a higher level of time accuracy and the best, time wise, synchronization with the peers in the network. - -### Block Version 7 - -[#PR1022](https://github.com/Aezora/AEZORA/pull/1022) defines Version 7 blocks, which remove the (now-unused) accumulator checkpoint from the block header. This results in an overall data reduction of ~256 bits from each block as well as the in-memory indexes. - -### New Network Message Signatures - -Layer 2 network messages (MN, Budget, Spork, etc) are now signed based on the hash of their **binary** content instead of their **string** representation ([#PR1024](https://github.com/Aezora/AEZORA/pull/1024)). - -### New SPORKS - -Two new SPORKS are introduced, `SPORK_17` ([#PR975](https://github.com/Aezora/AEZORA/pull/975)) and `SPORK_18` ([#PR995](https://github.com/Aezora/AEZORA/pull/995)).
-`SPORK_17` (off by default) is used to activate the [Cold Staking](#cold-staking) protocol. When this spork is off, no cold-staked block is accepted by the network and new delegations are rejected, but coin-owners are still able to spend previously created pay-to-cold-stake delegations. - -`SPORK_18` (off by default) is used to switch between Version 3 and [Version 4 Public Spends](#v1-zazr-spending-public-spends-version-4). When this spork is active, only version 4 spends are accepted by the network. When it's not, only version 3 spends are accepted. - -RPC Changes --------------- - -### New options for existing wallet commands - -A new (optional) argument, `includeDelegated`, has been added to the following commands that allows these commands to include delegated coins/information in their operation: -- `getbalance` - Boolean (Default: True) -- `sendfrom` - Boolean (Default: False) -- `sendmany` - Boolean (Default: False) -- `listtransactions` - Boolean (Default: True) - -Additionally, a new (optional) argument, `includeCold`, has been added to the `listtransactions` command (Boolean - Default: True), which allows for filtering of cold-staker delegated transactions. - -### New return fields for existing commands - -The `validateaddress` command now includes an additional response field, `isstaking`, to indicate wither or not the specified address is a cold staking address. - -The `getwalletinfo` command now includes two additional response fields: -- `delegated_balance` - AZR balance held in P2CS contracts (delegated amount total). -- `cold_staking_balance` - AZR balance held in cold staking addresses. - -### Newly introduced commands - -The following new commands have been added to the RPC interface: -- `getnewstakingaddress` -- `delegatestake` -- `rawdelegatestake` -- `getcoldstakingbalance` -- `delegatoradd` -- `delegatorremove` -- `listcoldutxos` -- `liststakingaddresses` -- `listdelegators` - -Details about each new command can be found below. - -`getnewstakingaddress` generates a new cold staking address: -``` -getnewstakingaddress ( "account" ) - -Returns a new AEZORA cold staking address for receiving delegated cold stakes. - -Arguments: -1. "account" (string, optional) The account name for the address to be linked to. if not provided, the default account "" is used. It can also be set to the empty string "" to represent the default account. The account does not need to exist, it will be created if there is no account by the given name. - -Result: -"aezoraaddress" (string) The new aezora address -``` - -`delegatestake` sends a cold staking delegation transaction: -``` -delegatestake "stakingaddress" amount ( "owneraddress" fExternalOwner fUseDelegated fForceNotEnabled ) - -Delegate an amount to a given address for cold staking. The amount is a real and is rounded to the nearest 0.00000001 - -Requires wallet passphrase to be set with walletpassphrase call. - -Arguments: -1. "stakingaddress" (string, required) The aezora staking address to delegate. -2. "amount" (numeric, required) The amount in AZR to delegate for staking. eg 100 -3. "owneraddress" (string, optional) The aezora address corresponding to the key that will be able to spend the stake. - If not provided, or empty string, a new wallet address is generated. -4. "fExternalOwner" (boolean, optional, default = false) use the provided 'owneraddress' anyway, even if not present in this wallet. - WARNING: The owner of the keys to 'owneraddress' will be the only one allowed to spend these coins. -5. "fUseDelegated" (boolean, optional, default = false) include already delegated inputs if needed.6. "fForceNotEnabled" (boolean, optional, default = false) force the creation even if SPORK 17 is disabled (for tests). - -Result: -{ - "owner_address": "xxx" (string) The owner (delegator) owneraddress. - "staker_address": "xxx" (string) The cold staker (delegate) stakingaddress. - "txid": "xxx" (string) The stake delegation transaction id. -} -``` - -`rawdelegatestake` creates a raw cold staking delegation transaction without broadcasting it to the network: -``` -rawdelegatestake "stakingaddress" amount ( "owneraddress" fExternalOwner fUseDelegated ) - -Delegate an amount to a given address for cold staking. The amount is a real and is rounded to the nearest 0.00000001 - -Delegate transaction is returned as json object. -Requires wallet passphrase to be set with walletpassphrase call. - -Arguments: -1. "stakingaddress" (string, required) The aezora staking address to delegate. -2. "amount" (numeric, required) The amount in AZR to delegate for staking. eg 100 -3. "owneraddress" (string, optional) The aezora address corresponding to the key that will be able to spend the stake. - If not provided, or empty string, a new wallet address is generated. -4. "fExternalOwner" (boolean, optional, default = false) use the provided 'owneraddress' anyway, even if not present in this wallet. - WARNING: The owner of the keys to 'owneraddress' will be the only one allowed to spend these coins. -5. "fUseDelegated (boolean, optional, default = false) include already delegated inputs if needed. - -Result: -{ - "txid" : "id", (string) The transaction id (same as provided) - "version" : n, (numeric) The version - "size" : n, (numeric) The serialized transaction size - "locktime" : ttt, (numeric) The lock time - "vin" : [ (array of json objects) - { - "txid": "id", (string) The transaction id - "vout": n, (numeric) - "scriptSig": { (json object) The script - "asm": "asm", (string) asm - "hex": "hex" (string) hex - }, - "sequence": n (numeric) The script sequence number - } - ,... - ], - "vout" : [ (array of json objects) - { - "value" : x.xxx, (numeric) The value in btc - "n" : n, (numeric) index - "scriptPubKey" : { (json object) - "asm" : "asm", (string) the asm - "hex" : "hex", (string) the hex - "reqSigs" : n, (numeric) The required sigs - "type" : "pubkeyhash", (string) The type, eg 'pubkeyhash' - "addresses" : [ (json array of string) - "aezoraaddress" (string) aezora address - ,... - ] - } - } - ,... - ], - "hex" : "data", (string) The serialized, hex-encoded data for 'txid' -} -``` - -`getcoldstakingbalance` returns the cold balance of the wallet: -``` -getcoldstakingbalance ( "account" ) - -If account is not specified, returns the server's total available cold balance. -If account is specified, returns the cold balance in the account. -Note that the account "" is not the same as leaving the parameter out. -The server total may be different to the balance in the default "" account. - -Arguments: -1. "account" (string, optional) The selected account, or "*" for entire wallet. It may be the default account using "". - -Result: -amount (numeric) The total amount in AZR received for this account in P2CS contracts. -``` - -`delegatoradd` whitelists a delegated owner address for cold staking: -``` -delegatoradd "addr" - -Add the provided address into the allowed delegators AddressBook. -This enables the staking of coins delegated to this wallet, owned by - -Arguments: -1. "addr" (string, required) The address to whitelist - -Result: -true|false (boolean) true if successful. -``` - -`delegatorremove` to remove previously whitelisted owner address: -``` -delegatoradd "addr" - -Add the provided address into the allowed delegators AddressBook. -This enables the staking of coins delegated to this wallet, owned by - -Arguments: -1. "addr" (string, required) The address to whitelist - -Result: -true|false (boolean) true if successful. -``` - -`listcoldutxos` lists all P2CS UTXOs belonging to the wallet (both delegator and cold staker): -``` -listcoldutxos ( nonWhitelistedOnly ) - -List P2CS unspent outputs received by this wallet as cold-staker- - -Arguments: -1. nonWhitelistedOnly (boolean, optional, default=false) Whether to exclude P2CS from whitelisted delegators. - -Result: -[ - { - "txid" : "true", (string) The transaction id of the P2CS utxo - "txidn" : "accountname", (string) The output number of the P2CS utxo - "amount" : x.xxx, (numeric) The amount of the P2CS utxo - "confirmations" : n (numeric) The number of confirmations of the P2CS utxo - "cold-staker" : n (string) The cold-staker address of the P2CS utxo - "coin-owner" : n (string) The coin-owner address of the P2CS utxo - "whitelisted" : n (string) "true"/"false" coin-owner in delegator whitelist - } - ,... -] -``` - -`liststakingaddresses` lists all cold staking addresses generated by the wallet: -``` -liststakingaddresses "addr" - -Shows the list of staking addresses for this wallet. - -Result: -[ - { - "label": "yyy", (string) account label - "address": "xxx", (string) AEZORA address string - } - ... -] -``` - -`listdelegators` lists the whitelisted owner addresses -``` -listdelegators "addr" - -Shows the list of allowed delegator addresses for cold staking. - -Result: -[ - { - "label": "yyy", (string) account label - "address": "xxx", (string) AEZORA address string - } - ... -] -``` - -Snapcraft Packages ------------------- - -For our linux users, in addition to the [Ubuntu PPA](https://launchpad.net/~aezora) repository, we are now offering a [Snap package](https://snapcraft.io/aezora-core) as quick way to install and update a AEZORA wallet. +*version* Change log +============== -Release versions are available via the `Stable` branch, and (for testing-only purposes) nightly builds are available in the `Beta` branch. +Detailed release notes follow. This overview includes changes that affect behavior, not code moves, refactors and string updates. For convenience in locating the code changes and accompanying discussion, both the pull request and git merge commit are mentioned. -Internal Miner/Staker Change --------------- +### Core Features -The wallet's internal miner/staker is no longer prevented from running prior to having synced all the additional layer 2 (MN/Budget) data. Instead, mining/staking uses better logic to allow block creation without fully synced layer 2 data when the full data set wouldn't be required. +### Build System -In other words, try to stake a new block only if: +### P2P Protocol and Network Code -- full layer 2 sync is complete -OR -- The spork list is synced and all three sporks (8,9 and 13) are **not** active. +### GUI -Faster Shutdown During Initial Loading --------------- +### RPC/REST -Previously, if a user wanted to close/quit the wallet before it had finished its initial loading process, they would need to wait until that loading process actually completed before the wallet would fully close. +Asm representations of scriptSig signatures now contain SIGHASH type decodes +---------------------------------------------------------------------------- -Now, the new behavior is to gracefully close the wallet once the current step is complete. +The `asm` property of each scriptSig now contains the decoded signature hash +type for each signature that provides a valid defined hash type. -*version* Change log -============== +The following items contain assembly representations of scriptSig signatures +and are affected by this change: -Detailed release notes follow. This overview includes changes that affect behavior, not code moves, refactors and string updates. For convenience in locating the code changes and accompanying discussion, both the pull request and git merge commit are mentioned. +- RPC `getrawtransaction` +- RPC `decoderawtransaction` +- REST `/rest/tx/` (JSON format) +- REST `/rest/block/` (JSON format when including extended tx details) +- `bitcoin-tx -json` -### Core Features +For example, the `scriptSig.asm` property of a transaction input that +previously showed an assembly representation of: -### Build System + 304502207fa7a6d1e0ee81132a269ad84e68d695483745cde8b541e3bf630749894e342a022100c1f7ab20e13e22fb95281a870f3dcf38d782e53023ee313d741ad0cfbc0c509001 -### P2P Protocol and Network Code +now shows as: -### GUI + 304502207fa7a6d1e0ee81132a269ad84e68d695483745cde8b541e3bf630749894e342a022100c1f7ab20e13e22fb95281a870f3dcf38d782e53023ee313d741ad0cfbc0c5090[ALL] -### RPC/REST +Note that the output of the RPC `decodescript` did not change because it is +configured specifically to process scriptPubKey and not scriptSig scripts. ### Wallet ### Miscellaneous - ## Credits Thanks to everyone who directly contributed to this release: diff --git a/share/genbuild.sh b/share/genbuild.sh index d3b1012b7..00e8efdfd 100644 --- a/share/genbuild.sh +++ b/share/genbuild.sh @@ -22,7 +22,7 @@ git_check_in_repo() { ! { git status --porcelain -uall --ignored "$@" 2>/dev/null || echo '??'; } | grep -q '?' } -DESC="1.1.0" +DESC="1.1.1" SUFFIX="" LAST_COMMIT_DATE="" if [ "${BITCOIN_GENBUILD_NO_GIT}" != "1" -a -e "$(which git 2>/dev/null)" -a "$(git rev-parse --is-inside-work-tree 2>/dev/null)" = "true" ] && git_check_in_repo share/genbuild.sh; then diff --git a/src/Makefile.am b/src/Makefile.am index f9251fea5..0d13bc563 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -127,7 +127,7 @@ BITCOIN_CORE_H = \ key.h \ key_io.h \ keystore.h \ - leveldbwrapper.h \ + dbwrapper.h \ limitedmap.h \ logging.h \ main.h \ @@ -230,7 +230,7 @@ libbitcoin_server_a_SOURCES = \ httprpc.cpp \ httpserver.cpp \ init.cpp \ - leveldbwrapper.cpp \ + dbwrapper.cpp \ main.cpp \ merkleblock.cpp \ miner.cpp \ diff --git a/src/Makefile.test.include b/src/Makefile.test.include index bc5231ca7..db54e037b 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -18,23 +18,26 @@ JSON_TEST_FILES = \ test/data/tx_valid.json \ test/data/sighash.json -RAW_TEST_FILES = test/data/alertTests.raw +RAW_TEST_FILES = GENERATED_TEST_FILES = $(JSON_TEST_FILES:.json=.json.h) $(RAW_TEST_FILES:.raw=.raw.h) BITCOIN_TEST_SUITE = \ test/test_aezora.h \ test/test_aezora.cpp + +if ENABLE_WALLET +BITCOIN_TEST_SUITE += \ + wallet/test/wallet_test_fixture.cpp \ + wallet/test/wallet_test_fixture.h +endif + # test_aezora binary # BITCOIN_TESTS =\ - test/zerocoin_implementation_tests.cpp\ - test/zerocoin_denomination_tests.cpp\ + test/arith_uint256_tests.cpp \ + test/zerocoin_denomination_tests.cpp \ test/zerocoin_transactions_tests.cpp \ - test/zerocoin_coinspend_tests.cpp \ test/zerocoin_bignum_tests.cpp \ - test/benchmark_zerocoin.cpp \ - test/tutorial_zerocoin.cpp \ - test/libzerocoin_tests.cpp \ test/addrman_tests.cpp \ test/allocator_tests.cpp \ test/base32_tests.cpp \ @@ -50,13 +53,16 @@ BITCOIN_TESTS =\ test/getarg_tests.cpp \ test/hash_tests.cpp \ test/key_tests.cpp \ + test/dbwrapper_tests.cpp \ test/main_tests.cpp \ test/mempool_tests.cpp \ test/merkle_tests.cpp \ test/mruset_tests.cpp \ test/multisig_tests.cpp \ + test/net_tests.cpp \ test/netbase_tests.cpp \ test/pmt_tests.cpp \ + test/prevector_tests.cpp \ test/random_tests.cpp \ test/reverselock_tests.cpp \ test/rpc_tests.cpp \ @@ -69,6 +75,7 @@ BITCOIN_TESTS =\ test/sighash_tests.cpp \ test/sigopcount_tests.cpp \ test/skiplist_tests.cpp \ + test/sync_tests.cpp \ test/timedata_tests.cpp \ test/torcontrol_tests.cpp \ test/transaction_tests.cpp \ @@ -80,7 +87,7 @@ if ENABLE_WALLET BITCOIN_TESTS += \ test/accounting_tests.cpp \ wallet/test/wallet_tests.cpp \ - test/rpc_wallet_tests.cpp + wallet/test/crypto_tests.cpp endif test_test_aezora_SOURCES = $(BITCOIN_TEST_SUITE) $(BITCOIN_TESTS) $(JSON_TEST_FILES) $(RAW_TEST_FILES) diff --git a/src/addrman.h b/src/addrman.h index 52e778b6c..087d31f8e 100644 --- a/src/addrman.h +++ b/src/addrman.h @@ -58,7 +58,7 @@ class CAddrInfo : public CAddress ADD_SERIALIZE_METHODS; template - inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) + inline void SerializationOp(Stream& s, Operation ser_action) { READWRITE(*(CAddress*)this); READWRITE(source); @@ -298,7 +298,7 @@ class CAddrMan * very little in common. */ template - void Serialize(Stream& s, int nType, int nVersionDummy) const + void Serialize(Stream& s) const { LOCK(cs); @@ -348,7 +348,7 @@ class CAddrMan } template - void Unserialize(Stream& s, int nType, int nVersionDummy) + void Unserialize(Stream& s) { LOCK(cs); @@ -445,10 +445,6 @@ class CAddrMan Check(); } - unsigned int GetSerializeSize(int nType, int nVersion) const - { - return (CSizeComputer(nType, nVersion) << *this).size(); - } void Clear() { diff --git a/src/aezora-tx.cpp b/src/aezora-tx.cpp index df49c1b56..ca8fd104c 100644 --- a/src/aezora-tx.cpp +++ b/src/aezora-tx.cpp @@ -220,12 +220,11 @@ static void MutateTxAddOutAddr(CMutableTransaction& tx, const std::string& strIn // extract and validate ADDRESS std::string strAddr = strInput.substr(pos + 1, std::string::npos); - CBitcoinAddress addr(strAddr); - if (!addr.IsValid()) + CTxDestination destination = DecodeDestination(strAddr); + if (!IsValidDestination(destination)) { throw std::runtime_error("invalid TX output address"); - - // build standard output script via GetScriptForDestination() - CScript scriptPubKey = GetScriptForDestination(addr.Get()); + } + CScript scriptPubKey = GetScriptForDestination(destination); // construct TxOut, append to transaction output list CTxOut txout(value, scriptPubKey); @@ -311,7 +310,7 @@ static bool findSighashFlags(int& flags, const std::string& flagStr) uint256 ParseHashUO(std::map& o, std::string strKey) { if (!o.count(strKey)) - return 0; + return UINT256_ZERO; return ParseHashUV(o[strKey], strKey); } @@ -388,8 +387,8 @@ static void MutateTxSign(CMutableTransaction& tx, const std::string& flagStr) CCoinsModifier coins = view.ModifyCoins(txid); if (coins->IsAvailable(nOut) && coins->vout[nOut].scriptPubKey != scriptPubKey) { std::string err("Previous output scriptPubKey mismatch:\n"); - err = err + coins->vout[nOut].scriptPubKey.ToString() + "\nvs:\n" + - scriptPubKey.ToString(); + err = err + ScriptToAsmStr(coins->vout[nOut].scriptPubKey) + "\nvs:\n"+ + ScriptToAsmStr(scriptPubKey); throw std::runtime_error(err); } if ((unsigned int)nOut >= coins->vout.size()) @@ -496,7 +495,7 @@ static void MutateTx(CMutableTransaction& tx, const std::string& command, const static void OutputTxJSON(const CTransaction& tx) { UniValue entry(UniValue::VOBJ); - TxToUniv(tx, 0, entry); + TxToUniv(tx, UINT256_ZERO, entry); std::string jsonOutput = entry.write(4); fprintf(stdout, "%s\n", jsonOutput.c_str()); diff --git a/src/amount.h b/src/amount.h index ce3d0111b..d05dba5b9 100644 --- a/src/amount.h +++ b/src/amount.h @@ -46,7 +46,7 @@ class CFeeRate ADD_SERIALIZE_METHODS; template - inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) + inline void SerializationOp(Stream& s, Operation ser_action) { READWRITE(nSatoshisPerK); } diff --git a/src/arith_uint256.h b/src/arith_uint256.h index 3b0230ffa..0ddf8457d 100644 --- a/src/arith_uint256.h +++ b/src/arith_uint256.h @@ -283,19 +283,14 @@ class base_uint return pn[0] | (uint64_t)pn[1] << 32; } - unsigned int GetSerializeSize(int nType, int nVersion) const - { - return sizeof(pn); - } - template - void Serialize(Stream& s, int nType, int nVersion) const + void Serialize(Stream& s) const { s.write((char*)pn, sizeof(pn)); } template - void Unserialize(Stream& s, int nType, int nVersion) + void Unserialize(Stream& s) { s.read((char*)pn, sizeof(pn)); } diff --git a/src/base58.h b/src/base58.h index 81cee0cf9..fc6c50a1b 100644 --- a/src/base58.h +++ b/src/base58.h @@ -179,8 +179,8 @@ class CBitcoinExtKeyBase : public CBase58Data CBitcoinExtKeyBase() {} }; -typedef CBitcoinExtKeyBase CBitcoinExtKey; -typedef CBitcoinExtKeyBase CBitcoinExtPubKey; +typedef CBitcoinExtKeyBase CBitcoinExtKey; +typedef CBitcoinExtKeyBase CBitcoinExtPubKey; CTxDestination DestinationFor(const CKeyID& keyID, const CChainParams::Base58Type addrType); diff --git a/src/blob_uint256.h b/src/blob_uint256.h index f586b2b44..e88004ae3 100644 --- a/src/blob_uint256.h +++ b/src/blob_uint256.h @@ -79,19 +79,14 @@ class base_blob return sizeof(data); } - unsigned int GetSerializeSize(int nType, int nVersion) const - { - return sizeof(data); - } - template - void Serialize(Stream& s, int nType, int nVersion) const + void Serialize(Stream& s) const { s.write((char*)data, sizeof(data)); } template - void Unserialize(Stream& s, int nType, int nVersion) + void Unserialize(Stream& s) { s.read((char*)data, sizeof(data)); } diff --git a/src/bloom.h b/src/bloom.h index 2c5cc0c1b..becf75b5c 100644 --- a/src/bloom.h +++ b/src/bloom.h @@ -70,7 +70,7 @@ class CBloomFilter ADD_SERIALIZE_METHODS; template - inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) + inline void SerializationOp(Stream& s, Operation ser_action) { READWRITE(vData); READWRITE(nHashFuncs); diff --git a/src/chain.h b/src/chain.h index a26ac3f0c..648c36b63 100644 --- a/src/chain.h +++ b/src/chain.h @@ -35,7 +35,7 @@ class CBlockFileInfo ADD_SERIALIZE_METHODS; template - inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) + inline void SerializationOp(Stream& s, Operation ser_action) { READWRITE(VARINT(nBlocks)); READWRITE(VARINT(nSize)); @@ -86,7 +86,7 @@ struct CDiskBlockPos { ADD_SERIALIZE_METHODS; template - inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) + inline void SerializationOp(Stream& s, Operation ser_action) { READWRITE(VARINT(nFile)); READWRITE(VARINT(nPos)); @@ -294,9 +294,10 @@ class CDiskBlockIndex : public CBlockIndex ADD_SERIALIZE_METHODS; template - inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nSerVersion) + inline void SerializationOp(Stream& s, Operation ser_action) { - if (!(nType & SER_GETHASH)) + int nSerVersion = s.GetVersion(); + if (!(s.GetType() & SER_GETHASH)) READWRITE(VARINT(nSerVersion)); READWRITE(VARINT(nHeight)); @@ -427,9 +428,10 @@ class CLegacyBlockIndex : public CBlockIndex ADD_SERIALIZE_METHODS; template - inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nSerVersion) + inline void SerializationOp(Stream& s, Operation ser_action) { - if (!(nType & SER_GETHASH)) + int nSerVersion = s.GetVersion(); + if (!(s.GetType() & SER_GETHASH)) READWRITE(VARINT(nSerVersion)); if (nSerVersion >= DBI_SER_VERSION_NO_ZC) { diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 0543db66f..7106a4e8d 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -71,7 +71,7 @@ static Checkpoints::MapCheckpoints mapCheckpoints = (90384, uint256S("309d8f656ff173abf8aeb04092bacd35eb69693e43d31530abfaf098a394bdd6")) (100330, uint256S("7afd2261cc8efdaf17844e0a5a125a789914836f790c19d898e2cfe1232a008a")) (181752, uint256S("3da55ef79f2c5166691074bddae58e5c6a2982ad0658577527f4ea8cdabe37e8")) - (201110, uint256S("e61cdeb9819a5b36e25aab3fda9af9fec91c93e625a2fe7406324f52be68a8bf")); + (206658, uint256S("68aab2ab67180adf11cb798b3573ff2bc5430ebd74d621edbb6fbbb15fd9a025")); static const Checkpoints::CCheckpointData data = { &mapCheckpoints, 1577461410, // * UNIX timestamp of last checkpoint block diff --git a/src/coins.h b/src/coins.h index a921df5a9..43c199252 100644 --- a/src/coins.h +++ b/src/coins.h @@ -174,32 +174,9 @@ class CCoins return fCoinStake; } - unsigned int GetSerializeSize(int nType, int nVersion) const - { - unsigned int nSize = 0; - unsigned int nMaskSize = 0, nMaskCode = 0; - CalcMaskSize(nMaskSize, nMaskCode); - bool fFirst = vout.size() > 0 && !vout[0].IsNull(); - bool fSecond = vout.size() > 1 && !vout[1].IsNull(); - assert(fFirst || fSecond || nMaskCode); - unsigned int nCode = 8 * (nMaskCode - (fFirst || fSecond ? 0 : 1)) + (fCoinBase ? 1 : 0) + (fCoinStake ? 2 : 0) + (fFirst ? 4 : 0) + (fSecond ? 8 : 0); - // version - nSize += ::GetSerializeSize(VARINT(this->nVersion), nType, nVersion); - // size of header code - nSize += ::GetSerializeSize(VARINT(nCode), nType, nVersion); - // spentness bitmask - nSize += nMaskSize; - // txouts themself - for (unsigned int i = 0; i < vout.size(); i++) - if (!vout[i].IsNull()) - nSize += ::GetSerializeSize(CTxOutCompressor(REF(vout[i])), nType, nVersion); - // height - nSize += ::GetSerializeSize(VARINT(nHeight), nType, nVersion); - return nSize; - } template - void Serialize(Stream& s, int nType, int nVersion) const + void Serialize(Stream& s) const { unsigned int nMaskSize = 0, nMaskCode = 0; CalcMaskSize(nMaskSize, nMaskCode); @@ -208,34 +185,34 @@ class CCoins assert(fFirst || fSecond || nMaskCode); unsigned int nCode = 16 * (nMaskCode - (fFirst || fSecond ? 0 : 1)) + (fCoinBase ? 1 : 0) + (fCoinStake ? 2 : 0) + (fFirst ? 4 : 0) + (fSecond ? 8 : 0); // version - ::Serialize(s, VARINT(this->nVersion), nType, nVersion); + ::Serialize(s, VARINT(this->nVersion)); // header code - ::Serialize(s, VARINT(nCode), nType, nVersion); + ::Serialize(s, VARINT(nCode)); // spentness bitmask for (unsigned int b = 0; b < nMaskSize; b++) { unsigned char chAvail = 0; for (unsigned int i = 0; i < 8 && 2 + b * 8 + i < vout.size(); i++) if (!vout[2 + b * 8 + i].IsNull()) chAvail |= (1 << i); - ::Serialize(s, chAvail, nType, nVersion); + ::Serialize(s, chAvail); } // txouts themself for (unsigned int i = 0; i < vout.size(); i++) { if (!vout[i].IsNull()) - ::Serialize(s, CTxOutCompressor(REF(vout[i])), nType, nVersion); + ::Serialize(s, CTxOutCompressor(REF(vout[i]))); } // coinbase height - ::Serialize(s, VARINT(nHeight), nType, nVersion); + ::Serialize(s, VARINT(nHeight)); } template - void Unserialize(Stream& s, int nType, int nVersion) + void Unserialize(Stream& s) { unsigned int nCode = 0; // version - ::Unserialize(s, VARINT(this->nVersion), nType, nVersion); + ::Unserialize(s, VARINT(nVersion)); // header code - ::Unserialize(s, VARINT(nCode), nType, nVersion); + ::Unserialize(s, VARINT(nCode)); fCoinBase = nCode & 1; //0001 - means coinbase fCoinStake = (nCode & 2) != 0; //0010 coinstake std::vector vAvail(2, false); @@ -245,7 +222,7 @@ class CCoins // spentness bitmask while (nMaskCode > 0) { unsigned char chAvail = 0; - ::Unserialize(s, chAvail, nType, nVersion); + ::Unserialize(s, chAvail); for (unsigned int p = 0; p < 8; p++) { bool f = (chAvail & (1 << p)) != 0; vAvail.push_back(f); @@ -257,10 +234,10 @@ class CCoins vout.assign(vAvail.size(), CTxOut()); for (unsigned int i = 0; i < vAvail.size(); i++) { if (vAvail[i]) - ::Unserialize(s, REF(CTxOutCompressor(vout[i])), nType, nVersion); + ::Unserialize(s, REF(CTxOutCompressor(vout[i]))); } // coinbase height - ::Unserialize(s, VARINT(nHeight), nType, nVersion); + ::Unserialize(s, VARINT(nHeight)); Cleanup(); } diff --git a/src/compressor.h b/src/compressor.h index 5d13e84d7..fdfb2d8d5 100644 --- a/src/compressor.h +++ b/src/compressor.h @@ -58,17 +58,8 @@ class CScriptCompressor public: CScriptCompressor(CScript& scriptIn) : script(scriptIn) {} - unsigned int GetSerializeSize(int nType, int nVersion) const - { - std::vector compr; - if (Compress(compr)) - return compr.size(); - unsigned int nSize = script.size() + nSpecialScripts; - return script.size() + VARINT(nSize).GetSerializeSize(nType, nVersion); - } - template - void Serialize(Stream& s, int nType, int nVersion) const + void Serialize(Stream& s) const { std::vector compr; if (Compress(compr)) { @@ -81,7 +72,7 @@ class CScriptCompressor } template - void Unserialize(Stream& s, int nType, int nVersion) + void Unserialize(Stream& s) { unsigned int nSize = 0; s >> VARINT(nSize); @@ -118,7 +109,7 @@ class CTxOutCompressor ADD_SERIALIZE_METHODS; template - inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) + inline void SerializationOp(Stream& s, Operation ser_action) { if (!ser_action.ForRead()) { uint64_t nVal = CompressAmount(txout.nValue); diff --git a/src/consensus/zerocoin_verify.cpp b/src/consensus/zerocoin_verify.cpp index e096a897a..4bfab81af 100644 --- a/src/consensus/zerocoin_verify.cpp +++ b/src/consensus/zerocoin_verify.cpp @@ -250,7 +250,7 @@ bool RecalculateAZRSupply(int nHeightStart, bool fSkipZazr) // Rewrite money supply nMoneySupply += (nValueOut - nValueIn); - // Rewrite zpiv supply too + // Rewrite zazr supply too if (!fSkipZazr && pindex->nHeight >= consensus.height_start_ZC) { UpdateZAZRSupplyConnect(block, pindex, true); } diff --git a/src/core_io.h b/src/core_io.h index 28bb0dd30..088945c08 100644 --- a/src/core_io.h +++ b/src/core_io.h @@ -17,6 +17,7 @@ class UniValue; // core_read.cpp extern CScript ParseScript(std::string s); +extern std::string ScriptToAsmStr(const CScript& script, const bool fAttemptSighashDecode = false); extern bool DecodeHexTx(CTransaction& tx, const std::string& strHexTx); extern bool DecodeHexBlk(CBlock&, const std::string& strHexBlk); extern uint256 ParseHashUV(const UniValue& v, const std::string& strName); @@ -26,9 +27,7 @@ extern std::vector ParseHexUV(const UniValue& v, const std::strin // core_write.cpp extern std::string FormatScript(const CScript& script); extern std::string EncodeHexTx(const CTransaction& tx); -extern void ScriptPubKeyToUniv(const CScript& scriptPubKey, - UniValue& out, - bool fIncludeHex); +extern void ScriptPubKeyToUniv(const CScript& scriptPubKey, UniValue& out, bool fIncludeHex); extern void TxToUniv(const CTransaction& tx, const uint256& hashBlock, UniValue& entry); #endif // BITCOIN_CORE_IO_H diff --git a/src/core_write.cpp b/src/core_write.cpp index 84a1c1ed6..6815cfbc9 100644 --- a/src/core_write.cpp +++ b/src/core_write.cpp @@ -16,6 +16,8 @@ #include "utilmoneystr.h" #include "utilstrencodings.h" +#include + std::string FormatScript(const CScript& script) @@ -53,6 +55,67 @@ std::string FormatScript(const CScript& script) return ret.substr(0, ret.size() - 1); } +const std::map mapSigHashTypes = + boost::assign::map_list_of + (static_cast(SIGHASH_ALL), std::string("ALL")) + (static_cast(SIGHASH_ALL|SIGHASH_ANYONECANPAY), std::string("ALL|ANYONECANPAY")) + (static_cast(SIGHASH_NONE), std::string("NONE")) + (static_cast(SIGHASH_NONE|SIGHASH_ANYONECANPAY), std::string("NONE|ANYONECANPAY")) + (static_cast(SIGHASH_SINGLE), std::string("SINGLE")) + (static_cast(SIGHASH_SINGLE|SIGHASH_ANYONECANPAY), std::string("SINGLE|ANYONECANPAY")) + ; + +/** + * Create the assembly string representation of a CScript object. + * @param[in] script CScript object to convert into the asm string representation. + * @param[in] fAttemptSighashDecode Whether to attempt to decode sighash types on data within the script that matches the format + * of a signature. Only pass true for scripts you believe could contain signatures. For example, + * pass false, or omit the this argument (defaults to false), for scriptPubKeys. + */ +std::string ScriptToAsmStr(const CScript& script, const bool fAttemptSighashDecode) +{ + std::string str; + opcodetype opcode; + std::vector vch; + CScript::const_iterator pc = script.begin(); + while (pc < script.end()) { + if (!str.empty()) { + str += " "; + } + if (!script.GetOp(pc, opcode, vch)) { + str += "[error]"; + return str; + } + if (0 <= opcode && opcode <= OP_PUSHDATA4) { + if (vch.size() <= static_cast::size_type>(4)) { + str += strprintf("%d", CScriptNum(vch, false).getint()); + } else { + // the IsUnspendable check makes sure not to try to decode OP_RETURN data that may match the format of a signature + if (fAttemptSighashDecode && !script.IsUnspendable()) { + std::string strSigHashDecode; + // goal: only attempt to decode a defined sighash type from data that looks like a signature within a scriptSig. + // this won't decode correctly formatted public keys in Pubkey or Multisig scripts due to + // the restrictions on the pubkey formats (see IsCompressedOrUncompressedPubKey) being incongruous with the + // checks in CheckSignatureEncoding. + if (CheckSignatureEncoding(vch, SCRIPT_VERIFY_STRICTENC, NULL)) { + const unsigned char chSigHashType = vch.back(); + if (mapSigHashTypes.count(chSigHashType)) { + strSigHashDecode = "[" + mapSigHashTypes.find(chSigHashType)->second + "]"; + vch.pop_back(); // remove the sighash type byte. it will be replaced by the decode. + } + } + str += HexStr(vch) + strSigHashDecode; + } else { + str += HexStr(vch); + } + } + } else { + str += GetOpName(opcode); + } + } + return str; +} + std::string EncodeHexTx(const CTransaction& tx) { CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION); @@ -68,7 +131,7 @@ void ScriptPubKeyToUniv(const CScript& scriptPubKey, std::vector addresses; int nRequired; - out.pushKV("asm", scriptPubKey.ToString()); + out.pushKV("asm", ScriptToAsmStr(scriptPubKey)); if (fIncludeHex) out.pushKV("hex", HexStr(scriptPubKey.begin(), scriptPubKey.end())); @@ -107,7 +170,7 @@ void TxToUniv(const CTransaction& tx, const uint256& hashBlock, UniValue& entry) in.pushKV("txid", txin.prevout.hash.GetHex()); in.pushKV("vout", (int64_t)txin.prevout.n); UniValue o(UniValue::VOBJ); - o.pushKV("asm", txin.scriptSig.ToString()); + o.pushKV("asm", ScriptToAsmStr(txin.scriptSig, true)); o.pushKV("hex", HexStr(txin.scriptSig.begin(), txin.scriptSig.end())); in.pushKV("scriptSig", o); } diff --git a/src/crypter.h b/src/crypter.h index d56dfe4d0..3ef4babef 100644 --- a/src/crypter.h +++ b/src/crypter.h @@ -48,7 +48,7 @@ class CMasterKey ADD_SERIALIZE_METHODS; template - inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) + inline void SerializationOp(Stream& s, Operation ser_action) { READWRITE(vchCryptedKey); READWRITE(vchSalt); diff --git a/src/leveldbwrapper.cpp b/src/dbwrapper.cpp similarity index 68% rename from src/leveldbwrapper.cpp rename to src/dbwrapper.cpp index e7b11b540..9c814af66 100644 --- a/src/leveldbwrapper.cpp +++ b/src/dbwrapper.cpp @@ -2,30 +2,19 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "leveldbwrapper.h" +#include "dbwrapper.h" #include "util.h" #include +#include #include #include #include #include +#include -void HandleError(const leveldb::Status& status) -{ - if (status.ok()) - return; - LogPrintf("%s\n", status.ToString()); - if (status.IsCorruption()) - throw leveldb_error("Database corrupted"); - if (status.IsIOError()) - throw leveldb_error("Database I/O error"); - if (status.IsNotFound()) - throw leveldb_error("Database entry missing"); - throw leveldb_error("Unknown database error"); -} static leveldb::Options GetOptions(size_t nCacheSize) { @@ -43,7 +32,7 @@ static leveldb::Options GetOptions(size_t nCacheSize) return options; } -CLevelDBWrapper::CLevelDBWrapper(const boost::filesystem::path& path, size_t nCacheSize, bool fMemory, bool fWipe) +CDBWrapper::CDBWrapper(const boost::filesystem::path& path, size_t nCacheSize, bool fMemory, bool fWipe) { penv = NULL; readoptions.verify_checksums = true; @@ -58,17 +47,18 @@ CLevelDBWrapper::CLevelDBWrapper(const boost::filesystem::path& path, size_t nCa } else { if (fWipe) { LogPrintf("Wiping LevelDB in %s\n", path.string()); - leveldb::DestroyDB(path.string(), options); + leveldb::Status result = leveldb::DestroyDB(path.string(), options); + dbwrapper_private::HandleError(result); } TryCreateDirectory(path); LogPrintf("Opening LevelDB in %s\n", path.string()); } leveldb::Status status = leveldb::DB::Open(options, path.string(), &pdb); - HandleError(status); + dbwrapper_private::HandleError(status); LogPrintf("Opened LevelDB successfully\n"); } -CLevelDBWrapper::~CLevelDBWrapper() +CDBWrapper::~CDBWrapper() { delete pdb; pdb = NULL; @@ -80,9 +70,40 @@ CLevelDBWrapper::~CLevelDBWrapper() options.env = NULL; } -bool CLevelDBWrapper::WriteBatch(CLevelDBBatch& batch, bool fSync) +bool CDBWrapper::WriteBatch(CDBBatch& batch, bool fSync) { leveldb::Status status = pdb->Write(fSync ? syncoptions : writeoptions, &batch.batch); - HandleError(status); + dbwrapper_private::HandleError(status); return true; } + +bool CDBWrapper::IsEmpty() +{ + boost::scoped_ptr it(NewIterator()); + it->SeekToFirst(); + return !(it->Valid()); +} + +CDBIterator::~CDBIterator() { delete piter; } +bool CDBIterator::Valid() { return piter->Valid(); } +void CDBIterator::SeekToFirst() { piter->SeekToFirst(); } +void CDBIterator::Next() { piter->Next(); } + + +namespace dbwrapper_private { + +void HandleError(const leveldb::Status& status) +{ + if (status.ok()) + return; + LogPrintf("%s\n", status.ToString()); + if (status.IsCorruption()) + throw dbwrapper_error("Database corrupted"); + if (status.IsIOError()) + throw dbwrapper_error("Database I/O error"); + if (status.IsNotFound()) + throw dbwrapper_error("Database entry missing"); + throw dbwrapper_error("Unknown database error"); +} + +}; diff --git a/src/leveldbwrapper.h b/src/dbwrapper.h similarity index 53% rename from src/leveldbwrapper.h rename to src/dbwrapper.h index 6f8427ae2..6c8a1a5bd 100644 --- a/src/leveldbwrapper.h +++ b/src/dbwrapper.h @@ -2,8 +2,8 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#ifndef BITCOIN_LEVELDBWRAPPER_H -#define BITCOIN_LEVELDBWRAPPER_H +#ifndef BITCOIN_DBWRAPPER_H +#define BITCOIN_DBWRAPPER_H #include "clientversion.h" #include "serialize.h" @@ -16,33 +16,50 @@ #include #include -class leveldb_error : public std::runtime_error + +static const size_t DBWRAPPER_PREALLOC_KEY_SIZE = 64; +static const size_t DBWRAPPER_PREALLOC_VALUE_SIZE = 1024; + + +class dbwrapper_error : public std::runtime_error { public: - leveldb_error(const std::string& msg) : std::runtime_error(msg) {} + dbwrapper_error(const std::string& msg) : std::runtime_error(msg) {} }; +class CDBWrapper; + +/** These should be considered an implementation detail of the specific database. + */ +namespace dbwrapper_private { + +/** Handle database error by throwing dbwrapper_error exception. + */ void HandleError(const leveldb::Status& status); -/** Batch of changes queued to be written to a CLevelDBWrapper */ -class CLevelDBBatch +}; + + +/** Batch of changes queued to be written to a CDBWrapper */ +class CDBBatch { - friend class CLevelDBWrapper; + friend class CDBWrapper; private: leveldb::WriteBatch batch; public: + template void Write(const K& key, const V& value) { CDataStream ssKey(SER_DISK, CLIENT_VERSION); - ssKey.reserve(ssKey.GetSerializeSize(key)); + ssKey.reserve(DBWRAPPER_PREALLOC_KEY_SIZE); ssKey << key; leveldb::Slice slKey(&ssKey[0], ssKey.size()); CDataStream ssValue(SER_DISK, CLIENT_VERSION); - ssValue.reserve(ssValue.GetSerializeSize(value)); + ssValue.reserve(DBWRAPPER_PREALLOC_VALUE_SIZE); ssValue << value; leveldb::Slice slValue(&ssValue[0], ssValue.size()); @@ -53,7 +70,7 @@ class CLevelDBBatch void Erase(const K& key) { CDataStream ssKey(SER_DISK, CLIENT_VERSION); - ssKey.reserve(ssKey.GetSerializeSize(key)); + ssKey.reserve(DBWRAPPER_PREALLOC_KEY_SIZE); ssKey << key; leveldb::Slice slKey(&ssKey[0], ssKey.size()); @@ -61,7 +78,65 @@ class CLevelDBBatch } }; -class CLevelDBWrapper +class CDBIterator +{ +private: + leveldb::Iterator *piter; + +public: + /** + * @param[in] _piter The original leveldb iterator. + */ + CDBIterator(leveldb::Iterator *_piter) : piter(_piter) { }; + ~CDBIterator(); + + bool Valid(); + + void SeekToFirst(); + + template void Seek(const K& key) { + CDataStream ssKey(SER_DISK, CLIENT_VERSION); + ssKey.reserve(DBWRAPPER_PREALLOC_KEY_SIZE); + ssKey << key; + leveldb::Slice slKey(&ssKey[0], ssKey.size()); + piter->Seek(slKey); + } + + void Next(); + + template bool GetKey(K& key) { + leveldb::Slice slKey = piter->key(); + try { + CDataStream ssKey(slKey.data(), slKey.data() + slKey.size(), SER_DISK, CLIENT_VERSION); + ssKey >> key; + } catch(std::exception &e) { + return false; + } + return true; + } + + unsigned int GetKeySize() { + return piter->key().size(); + } + + template bool GetValue(V& value) { + leveldb::Slice slValue = piter->value(); + try { + CDataStream ssValue(slValue.data(), slValue.data() + slValue.size(), SER_DISK, CLIENT_VERSION); + ssValue >> value; + } catch(std::exception &e) { + return false; + } + return true; + } + + unsigned int GetValueSize() { + return piter->value().size(); + } + +}; + +class CDBWrapper { private: //! custom environment this database is using (may be NULL in case of default environment) @@ -86,14 +161,20 @@ class CLevelDBWrapper leveldb::DB* pdb; public: - CLevelDBWrapper(const boost::filesystem::path& path, size_t nCacheSize, bool fMemory = false, bool fWipe = false); - ~CLevelDBWrapper(); + /** + * @param[in] path Location in the filesystem where leveldb data will be stored. + * @param[in] nCacheSize Configures various leveldb cache settings. + * @param[in] fMemory If true, use leveldb's memory environment. + * @param[in] fWipe If true, remove all existing data. + */ + CDBWrapper(const boost::filesystem::path& path, size_t nCacheSize, bool fMemory = false, bool fWipe = false); + ~CDBWrapper(); template bool Read(const K& key, V& value) const { CDataStream ssKey(SER_DISK, CLIENT_VERSION); - ssKey.reserve(ssKey.GetSerializeSize(key)); + ssKey.reserve(DBWRAPPER_PREALLOC_KEY_SIZE); ssKey << key; leveldb::Slice slKey(&ssKey[0], ssKey.size()); @@ -103,7 +184,7 @@ class CLevelDBWrapper if (status.IsNotFound()) return false; LogPrintf("LevelDB read failure: %s\n", status.ToString()); - HandleError(status); + dbwrapper_private::HandleError(status); } try { CDataStream ssValue(strValue.data(), strValue.data() + strValue.size(), SER_DISK, CLIENT_VERSION); @@ -117,7 +198,7 @@ class CLevelDBWrapper template bool Write(const K& key, const V& value, bool fSync = false) { - CLevelDBBatch batch; + CDBBatch batch; batch.Write(key, value); return WriteBatch(batch, fSync); } @@ -126,7 +207,7 @@ class CLevelDBWrapper bool Exists(const K& key) const { CDataStream ssKey(SER_DISK, CLIENT_VERSION); - ssKey.reserve(ssKey.GetSerializeSize(key)); + ssKey.reserve(DBWRAPPER_PREALLOC_KEY_SIZE); ssKey << key; leveldb::Slice slKey(&ssKey[0], ssKey.size()); @@ -136,7 +217,7 @@ class CLevelDBWrapper if (status.IsNotFound()) return false; LogPrintf("LevelDB read failure: %s\n", status.ToString()); - HandleError(status); + dbwrapper_private::HandleError(status); } return true; } @@ -144,12 +225,12 @@ class CLevelDBWrapper template bool Erase(const K& key, bool fSync = false) { - CLevelDBBatch batch; + CDBBatch batch; batch.Erase(key); return WriteBatch(batch, fSync); } - bool WriteBatch(CLevelDBBatch& batch, bool fSync = false); + bool WriteBatch(CDBBatch& batch, bool fSync = false); // not available for LevelDB; provide for compatibility with BDB bool Flush() @@ -159,15 +240,21 @@ class CLevelDBWrapper bool Sync() { - CLevelDBBatch batch; + CDBBatch batch; return WriteBatch(batch, true); } // not exactly clean encapsulation, but it's easiest for now - leveldb::Iterator* NewIterator() + CDBIterator* NewIterator() { - return pdb->NewIterator(iteroptions); + return new CDBIterator(pdb->NewIterator(iteroptions)); } + + /** + * Return true if the database managed by this class contains no entries. + */ + bool IsEmpty(); + }; -#endif // BITCOIN_LEVELDBWRAPPER_H +#endif // BITCOIN_DBWRAPPER_H diff --git a/src/hash.h b/src/hash.h index f5f1a948c..b10c7d413 100644 --- a/src/hash.h +++ b/src/hash.h @@ -279,16 +279,19 @@ class CHashWriter private: CHash256 ctx; + const int nType; + const int nVersion; + public: - int nType; - int nVersion; CHashWriter(int nTypeIn, int nVersionIn) : nType(nTypeIn), nVersion(nVersionIn) {} - CHashWriter& write(const char* pch, size_t size) + int GetType() const { return nType; } + int GetVersion() const { return nVersion; } + + void write(const char* pch, size_t size) { ctx.Write((const unsigned char*)pch, size); - return (*this); } // invalidates the object @@ -303,7 +306,7 @@ class CHashWriter CHashWriter& operator<<(const T& obj) { // Serialize to this stream - ::Serialize(*this, obj, nType, nVersion); + ::Serialize(*this, obj); return (*this); } }; diff --git a/src/init.cpp b/src/init.cpp index 3a00d37fc..20a342991 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1561,7 +1561,7 @@ bool AppInit2() // Recalculate money supply if (fReindexMoneySupply) { LOCK(cs_main); - // Skip zpiv if already reindexed + // Skip zazr if already reindexed RecalculateAZRSupply(1, fReindexZerocoin); } diff --git a/src/key.cpp b/src/key.cpp index 399398491..1a62559fc 100644 --- a/src/key.cpp +++ b/src/key.cpp @@ -323,7 +323,7 @@ CExtPubKey CExtKey::Neuter() const return ret; } -void CExtKey::Encode(unsigned char code[74]) const +void CExtKey::Encode(unsigned char code[BIP32_EXTKEY_SIZE]) const { code[0] = nDepth; memcpy(code + 1, vchFingerprint, 4); @@ -337,13 +337,13 @@ void CExtKey::Encode(unsigned char code[74]) const memcpy(code + 42, key.begin(), 32); } -void CExtKey::Decode(const unsigned char code[74]) +void CExtKey::Decode(const unsigned char code[BIP32_EXTKEY_SIZE]) { nDepth = code[0]; memcpy(vchFingerprint, code + 1, 4); nChild = (code[5] << 24) | (code[6] << 16) | (code[7] << 8) | code[8]; memcpy(chaincode.begin(), code + 9, 32); - key.Set(code + 42, code + 74, true); + key.Set(code + 42, code + BIP32_EXTKEY_SIZE, true); } bool ECC_InitSanityCheck() diff --git a/src/libzerocoin/Accumulator.h b/src/libzerocoin/Accumulator.h index 24cd1fd49..3ca66f8c5 100644 --- a/src/libzerocoin/Accumulator.h +++ b/src/libzerocoin/Accumulator.h @@ -41,7 +41,7 @@ class Accumulator { Accumulator(const ZerocoinParams* p, const CoinDenomination d, CBigNum bnValue = 0); ADD_SERIALIZE_METHODS; template - inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) + inline void SerializationOp(Stream& s, Operation ser_action) { READWRITE(value); READWRITE(denomination); diff --git a/src/libzerocoin/Coin.h b/src/libzerocoin/Coin.h index 958ec3453..3d780dfdb 100644 --- a/src/libzerocoin/Coin.h +++ b/src/libzerocoin/Coin.h @@ -75,7 +75,7 @@ class PublicCoin ADD_SERIALIZE_METHODS; template - inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) + inline void SerializationOp(Stream& s, Operation ser_action) { READWRITE(value); READWRITE(denomination); @@ -129,7 +129,7 @@ class PrivateCoin ADD_SERIALIZE_METHODS; template - inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) + inline void SerializationOp(Stream& s, Operation ser_action) { READWRITE(publicCoin); READWRITE(randomness); diff --git a/src/libzerocoin/CoinRandomnessSchnorrSignature.h b/src/libzerocoin/CoinRandomnessSchnorrSignature.h index 9ebf8493e..bf85079db 100644 --- a/src/libzerocoin/CoinRandomnessSchnorrSignature.h +++ b/src/libzerocoin/CoinRandomnessSchnorrSignature.h @@ -41,7 +41,7 @@ class CoinRandomnessSchnorrSignature { ADD_SERIALIZE_METHODS; template - inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) + inline void SerializationOp(Stream& s, Operation ser_action) { READWRITE(alpha); READWRITE(beta); diff --git a/src/libzerocoin/CoinSpend.h b/src/libzerocoin/CoinSpend.h index a99b4e13e..705a32342 100644 --- a/src/libzerocoin/CoinSpend.h +++ b/src/libzerocoin/CoinSpend.h @@ -35,7 +35,7 @@ class AccumulatorProofOfKnowledge { AccumulatorProofOfKnowledge() {}; ADD_SERIALIZE_METHODS; template - inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) + inline void SerializationOp(Stream& s, Operation ser_action) { READWRITE(C_e); READWRITE(C_u); READWRITE(C_r); READWRITE(st_1); READWRITE(st_2); READWRITE(st_3); READWRITE(t_1); READWRITE(t_2); READWRITE(t_3); READWRITE(t_4); READWRITE(s_alpha); READWRITE(s_beta); @@ -58,7 +58,7 @@ class SerialNumberSignatureOfKnowledge { SerialNumberSignatureOfKnowledge(){}; ADD_SERIALIZE_METHODS; template - inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) + inline void SerializationOp(Stream& s, Operation ser_action) { READWRITE(s_notprime); READWRITE(sprime); @@ -77,7 +77,7 @@ class CommitmentProofOfKnowledge { CommitmentProofOfKnowledge() {}; ADD_SERIALIZE_METHODS; template - inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) + inline void SerializationOp(Stream& s, Operation ser_action) { READWRITE(S1); READWRITE(S2); READWRITE(S3); READWRITE(challenge); } @@ -125,7 +125,7 @@ class CoinSpend ADD_SERIALIZE_METHODS; template - inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) + inline void SerializationOp(Stream& s, Operation ser_action) { READWRITE(denomination); READWRITE(ptxHash); diff --git a/src/libzerocoin/Commitment.h b/src/libzerocoin/Commitment.h index 86d7061f8..4a3b55e0d 100644 --- a/src/libzerocoin/Commitment.h +++ b/src/libzerocoin/Commitment.h @@ -56,7 +56,7 @@ class Commitment { ADD_SERIALIZE_METHODS; template - inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) + inline void SerializationOp(Stream& s, Operation ser_action) { READWRITE(commitmentValue); READWRITE(randomness); READWRITE(contents); } diff --git a/src/libzerocoin/Params.h b/src/libzerocoin/Params.h index 9ef709913..dcb48c226 100644 --- a/src/libzerocoin/Params.h +++ b/src/libzerocoin/Params.h @@ -57,7 +57,7 @@ class IntegerGroupParams { CBigNum groupOrder; ADD_SERIALIZE_METHODS; - template inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { + template inline void SerializationOp(Stream& s, Operation ser_action) { READWRITE(initialized); READWRITE(g); READWRITE(h); @@ -140,7 +140,7 @@ class AccumulatorAndProofParams { */ uint32_t k_dprime; ADD_SERIALIZE_METHODS; - template inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { + template inline void SerializationOp(Stream& s, Operation ser_action) { READWRITE(initialized); READWRITE(accumulatorModulus); READWRITE(accumulatorBase); @@ -205,7 +205,7 @@ class ZerocoinParams { uint32_t zkp_hash_len; ADD_SERIALIZE_METHODS; - template inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { + template inline void SerializationOp(Stream& s, Operation ser_action) { READWRITE(initialized); READWRITE(accumulatorParams); READWRITE(coinCommitmentGroup); diff --git a/src/libzerocoin/bignum.h b/src/libzerocoin/bignum.h index 8707694d4..3c158436d 100644 --- a/src/libzerocoin/bignum.h +++ b/src/libzerocoin/bignum.h @@ -98,22 +98,17 @@ class CBigNum std::string GetHex() const; std::string GetDec() const; - unsigned int GetSerializeSize(int nType=0, int nVersion=PROTOCOL_VERSION) const - { - return ::GetSerializeSize(getvch(), nType, nVersion); - } - template - void Serialize(Stream& s, int nType=0, int nVersion=PROTOCOL_VERSION) const + void Serialize(Stream& s) const { - ::Serialize(s, getvch(), nType, nVersion); + ::Serialize(s, getvch()); } template - void Unserialize(Stream& s, int nType=0, int nVersion=PROTOCOL_VERSION) + void Unserialize(Stream& s) { std::vector vch; - ::Unserialize(s, vch, nType, nVersion); + ::Unserialize(s, vch); setvch(vch); } diff --git a/src/main.cpp b/src/main.cpp index 4196a4eb8..4f5600e46 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -99,7 +99,7 @@ size_t nCoinCacheUsage = 5000 * 300; /* If the tip is older than this (in seconds), the node is considered to be in initial block download. */ int64_t nMaxTipAge = DEFAULT_MAX_TIP_AGE; -/** Fees smaller than this (in upiv) are considered zero fee (for relaying and mining) +/** Fees smaller than this (in uazr) are considered zero fee (for relaying and mining) * We are ~100 times smaller then bitcoin now (2015-06-23), set minRelayTxFee only 10 times higher * so it's still 10 times lower comparing to bitcoin. */ @@ -646,7 +646,7 @@ bool AddOrphanTx(const CTransaction& tx, NodeId peer) // have been mined or received. // 10,000 orphans, each of which is at most 5,000 bytes big is // at most 500 megabytes of orphans: - unsigned int sz = tx.GetSerializeSize(SER_NETWORK, CTransaction::CURRENT_VERSION); + unsigned int sz = GetSerializeSize(tx, SER_NETWORK, CTransaction::CURRENT_VERSION); if (sz > 5000) { LogPrint(BCLog::MEMPOOL, "ignoring large orphan tx (size: %u, hash: %s)\n", sz, hash.ToString()); return false; @@ -742,7 +742,7 @@ bool IsStandardTx(const CTransaction& tx, std::string& reason) // almost as much to process as they cost the sender in fees, because // computing signature hashes is O(ninputs*txsize). Limiting transactions // to MAX_STANDARD_TX_SIZE mitigates CPU exhaustion attacks. - unsigned int sz = tx.GetSerializeSize(SER_NETWORK, CTransaction::CURRENT_VERSION); + unsigned int sz = GetSerializeSize(tx, SER_NETWORK, CTransaction::CURRENT_VERSION); unsigned int nMaxSize = tx.ContainsZerocoins() ? MAX_ZEROCOIN_TX_SIZE : MAX_STANDARD_TX_SIZE; if (sz >= nMaxSize) { reason = "tx-size"; @@ -1505,7 +1505,7 @@ bool WriteBlockToDisk(CBlock& block, CDiskBlockPos& pos) return error("WriteBlockToDisk : OpenBlockFile failed"); // Write index header - unsigned int nSize = fileout.GetSerializeSize(block); + unsigned int nSize = GetSerializeSize(fileout, block); fileout << FLATDATA(Params().MessageStart()) << nSize; // Write block @@ -3725,7 +3725,7 @@ bool CheckWork(const CBlock block, CBlockIndex* const pindexPrev) } if (block.nBits != nBitsRequired) { - // Pivx Specific reference to the block with the wrong threshold was used. + // Aezora Specific reference to the block with the wrong threshold was used. const Consensus::Params& consensus = Params().GetConsensus(); if ((block.nTime == (uint32_t) consensus.nAezoraBadBlockTime) && (block.nBits == (uint32_t) consensus.nAezoraBadBlockBits)) { @@ -4319,7 +4319,7 @@ bool ProcessNewBlock(CValidationState& state, CNode* pfrom, CBlock* pblock, CDis } LogPrintf("%s : ACCEPTED Block %ld in %ld milliseconds with size=%d\n", __func__, GetHeight(), GetTimeMillis() - nStartTime, - pblock->GetSerializeSize(SER_DISK, CLIENT_VERSION)); + GetSerializeSize(*pblock, SER_DISK, CLIENT_VERSION)); return true; } @@ -6081,14 +6081,14 @@ bool static ProcessMessage(CNode* pfrom, std::string strCommand, CDataStream& vR // it was the one which was commented out int ActiveProtocol() { - // SPORK_14 was used for 70920 (v1.0), commented out now. -// if (sporkManager.IsSporkActive(SPORK_14_NEW_PROTOCOL_ENFORCEMENT)) -// return MIN_PEER_PROTO_VERSION_AFTER_ENFORCEMENT; - - // SPORK_15 is used for 70921 (v1.1+) - if (sporkManager.IsSporkActive(SPORK_15_NEW_PROTOCOL_ENFORCEMENT_2)) + // SPORK_14 was used for 70923 (v1.1.1), commented out now. + if (sporkManager.IsSporkActive(SPORK_14_NEW_PROTOCOL_ENFORCEMENT)) return MIN_PEER_PROTO_VERSION_AFTER_ENFORCEMENT; + // SPORK_15 is used for 70922 (v1.1.0) +// if (sporkManager.IsSporkActive(SPORK_15_NEW_PROTOCOL_ENFORCEMENT_2)) +// return MIN_PEER_PROTO_VERSION_AFTER_ENFORCEMENT; + return MIN_PEER_PROTO_VERSION_BEFORE_ENFORCEMENT; } @@ -6426,7 +6426,7 @@ bool CBlockUndo::WriteToDisk(CDiskBlockPos& pos, const uint256& hashBlock) return error("CBlockUndo::WriteToDisk : OpenUndoFile failed"); // Write index header - unsigned int nSize = fileout.GetSerializeSize(*this); + unsigned int nSize = GetSerializeSize(fileout, *this); fileout << FLATDATA(Params().MessageStart()) << nSize; // Write undo data diff --git a/src/masternode-budget.cpp b/src/masternode-budget.cpp index 8125194a6..4a04eb553 100644 --- a/src/masternode-budget.cpp +++ b/src/masternode-budget.cpp @@ -51,7 +51,7 @@ bool IsBudgetCollateralValid(uint256 nTxCollateralHash, uint256 nExpectedHash, s // Collateral for budget finalization // Note: there are still old valid budgets out there, but the check for the new 5 AZR finalization collateral // will also cover the old 50 AZR finalization collateral. - LogPrint(BCLog::MNBUDGET, "Final Budget: o.scriptPubKey(%s) == findScript(%s) ?\n", o.scriptPubKey.ToString(), findScript.ToString()); + LogPrint(BCLog::MNBUDGET, "Final Budget: o.scriptPubKey(%s) == findScript(%s) ?\n", HexStr(o.scriptPubKey), HexStr(findScript)); if (o.scriptPubKey == findScript) { LogPrint(BCLog::MNBUDGET, "Final Budget: o.nValue(%ld) >= BUDGET_FEE_TX(%ld) ?\n", o.nValue, BUDGET_FEE_TX); if(o.nValue >= BUDGET_FEE_TX) { @@ -61,7 +61,7 @@ bool IsBudgetCollateralValid(uint256 nTxCollateralHash, uint256 nExpectedHash, s } else { // Collateral for normal budget proposal - LogPrint(BCLog::MNBUDGET, "Normal Budget: o.scriptPubKey(%s) == findScript(%s) ?\n", o.scriptPubKey.ToString(), findScript.ToString()); + LogPrint(BCLog::MNBUDGET, "Normal Budget: o.scriptPubKey(%s) == findScript(%s) ?\n", HexStr(o.scriptPubKey), HexStr(findScript)); if (o.scriptPubKey == findScript) { LogPrint(BCLog::MNBUDGET, "Normal Budget: o.nValue(%ld) >= PROPOSAL_FEE_TX(%ld) ?\n", o.nValue, PROPOSAL_FEE_TX); if(o.nValue >= PROPOSAL_FEE_TX) { @@ -1912,13 +1912,13 @@ void CFinalizedBudget::CheckAndVote() for (unsigned int i = 0; i < vecBudgetPaymentsSortedByHash.size(); i++) { LogPrint(BCLog::MNBUDGET,"CFinalizedBudget::AutoCheck Budget-Payments - nProp %d %s\n", i, vecBudgetPaymentsSortedByHash[i].nProposalHash.ToString()); - LogPrint(BCLog::MNBUDGET,"CFinalizedBudget::AutoCheck Budget-Payments - Payee %d %s\n", i, vecBudgetPaymentsSortedByHash[i].payee.ToString()); + LogPrint(BCLog::MNBUDGET,"CFinalizedBudget::AutoCheck Budget-Payments - Payee %d %s\n", i, HexStr(vecBudgetPaymentsSortedByHash[i].payee)); LogPrint(BCLog::MNBUDGET,"CFinalizedBudget::AutoCheck Budget-Payments - nAmount %d %lli\n", i, vecBudgetPaymentsSortedByHash[i].nAmount); } for (unsigned int i = 0; i < vBudgetProposalsSortedByHash.size(); i++) { LogPrint(BCLog::MNBUDGET,"CFinalizedBudget::AutoCheck Budget-Proposals - nProp %d %s\n", i, vBudgetProposalsSortedByHash[i]->GetHash().ToString()); - LogPrint(BCLog::MNBUDGET,"CFinalizedBudget::AutoCheck Budget-Proposals - Payee %d %s\n", i, vBudgetProposalsSortedByHash[i]->GetPayee().ToString()); + LogPrint(BCLog::MNBUDGET,"CFinalizedBudget::AutoCheck Budget-Proposals - Payee %d %s\n", i, HexStr(vBudgetProposalsSortedByHash[i]->GetPayee())); LogPrint(BCLog::MNBUDGET,"CFinalizedBudget::AutoCheck Budget-Proposals - nAmount %d %lli\n", i, vBudgetProposalsSortedByHash[i]->GetAmount()); } @@ -1945,8 +1945,8 @@ void CFinalizedBudget::CheckAndVote() } // if(vecBudgetPayments[i].payee != vBudgetProposals[i]->GetPayee()){ -- triggered with false positive - if (vecBudgetPaymentsSortedByHash[i].payee.ToString() != vBudgetProposalsSortedByHash[i]->GetPayee().ToString()) { - LogPrint(BCLog::MNBUDGET,"CFinalizedBudget::AutoCheck - item #%d payee doesn't match %s %s\n", i, vecBudgetPaymentsSortedByHash[i].payee.ToString(), vBudgetProposalsSortedByHash[i]->GetPayee().ToString()); + if (HexStr(vecBudgetPaymentsSortedByHash[i].payee) != HexStr(vBudgetProposalsSortedByHash[i]->GetPayee())) { + LogPrint(BCLog::MNBUDGET,"CFinalizedBudget::AutoCheck - item #%d payee doesn't match %s %s\n", i, HexStr(vecBudgetPaymentsSortedByHash[i].payee), HexStr(vBudgetProposalsSortedByHash[i]->GetPayee())); return; } @@ -2160,7 +2160,7 @@ TrxValidationStatus CFinalizedBudget::IsTransactionValid(const CTransaction& txN for (CTxOut out : txNew.vout) { LogPrint(BCLog::MNBUDGET,"CFinalizedBudget::IsTransactionValid - nCurrentBudgetPayment=%d, payee=%s == out.scriptPubKey=%s, amount=%ld == out.nValue=%ld\n", - nCurrentBudgetPayment, vecBudgetPayments[nCurrentBudgetPayment].payee.ToString().c_str(), out.scriptPubKey.ToString().c_str(), + nCurrentBudgetPayment, HexStr(vecBudgetPayments[nCurrentBudgetPayment].payee), HexStr(out.scriptPubKey), vecBudgetPayments[nCurrentBudgetPayment].nAmount, out.nValue); if (vecBudgetPayments[nCurrentBudgetPayment].payee == out.scriptPubKey && vecBudgetPayments[nCurrentBudgetPayment].nAmount == out.nValue) { diff --git a/src/masternode-budget.h b/src/masternode-budget.h index 2d1f6dfa2..5501864f2 100644 --- a/src/masternode-budget.h +++ b/src/masternode-budget.h @@ -88,7 +88,7 @@ class CBudgetVote : public CSignedMessage ADD_SERIALIZE_METHODS; template - inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) + inline void SerializationOp(Stream& s, Operation ser_action) { READWRITE(vin); READWRITE(nProposalHash); @@ -131,7 +131,7 @@ class CFinalizedBudgetVote : public CSignedMessage ADD_SERIALIZE_METHODS; template - inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) + inline void SerializationOp(Stream& s, Operation ser_action) { READWRITE(vin); READWRITE(nBudgetHash); @@ -263,7 +263,7 @@ class CBudgetManager ADD_SERIALIZE_METHODS; template - inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) + inline void SerializationOp(Stream& s, Operation ser_action) { READWRITE(mapSeenMasternodeBudgetProposals); READWRITE(mapSeenMasternodeBudgetVotes); @@ -296,7 +296,7 @@ class CTxBudgetPayment //for saving to the serialized db template - inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) + inline void SerializationOp(Stream& s, Operation ser_action) { READWRITE(*(CScriptBase*)(&payee)); READWRITE(nAmount); @@ -388,7 +388,7 @@ class CFinalizedBudget //for saving to the serialized db template - inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) + inline void SerializationOp(Stream& s, Operation ser_action) { READWRITE(LIMITED_STRING(strBudgetName, 20)); READWRITE(nFeeTXHash); @@ -436,7 +436,7 @@ class CFinalizedBudgetBroadcast : public CFinalizedBudget //for propagating messages template - inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) + inline void SerializationOp(Stream& s, Operation ser_action) { //for syncing with other clients READWRITE(LIMITED_STRING(strBudgetName, 20)); @@ -528,7 +528,7 @@ class CBudgetProposal ADD_SERIALIZE_METHODS; template - inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) + inline void SerializationOp(Stream& s, Operation ser_action) { //for syncing with other clients READWRITE(LIMITED_STRING(strProposalName, 20)); @@ -584,7 +584,7 @@ class CBudgetProposalBroadcast : public CBudgetProposal ADD_SERIALIZE_METHODS; template - inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) + inline void SerializationOp(Stream& s, Operation ser_action) { //for syncing with other clients diff --git a/src/masternode-payments.cpp b/src/masternode-payments.cpp index d82e2684f..18c72f8ac 100644 --- a/src/masternode-payments.cpp +++ b/src/masternode-payments.cpp @@ -156,7 +156,7 @@ uint256 CMasternodePaymentWinner::GetHash() const std::string CMasternodePaymentWinner::GetStrMessage() const { - return vinMasternode.prevout.ToStringShort() + std::to_string(nBlockHeight) + payee.ToString(); + return vinMasternode.prevout.ToStringShort() + std::to_string(nBlockHeight) + HexStr(payee); } bool CMasternodePaymentWinner::IsValid(CNode* pnode, std::string& strError) diff --git a/src/masternode-payments.h b/src/masternode-payments.h index e8972aa3f..a2226bb9a 100644 --- a/src/masternode-payments.h +++ b/src/masternode-payments.h @@ -77,7 +77,7 @@ class CMasternodePayee ADD_SERIALIZE_METHODS; template - inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) + inline void SerializationOp(Stream& s, Operation ser_action) { READWRITE(*(CScriptBase*)(&scriptPubKey)); READWRITE(nVotes); @@ -149,7 +149,7 @@ class CMasternodeBlockPayees ADD_SERIALIZE_METHODS; template - inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) + inline void SerializationOp(Stream& s, Operation ser_action) { READWRITE(nBlockHeight); READWRITE(vecPayments); @@ -196,7 +196,7 @@ class CMasternodePaymentWinner : public CSignedMessage ADD_SERIALIZE_METHODS; template - inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) + inline void SerializationOp(Stream& s, Operation ser_action) { READWRITE(vinMasternode); READWRITE(nBlockHeight); @@ -215,7 +215,7 @@ class CMasternodePaymentWinner : public CSignedMessage std::string ret = ""; ret += vinMasternode.ToString(); ret += ", " + std::to_string(nBlockHeight); - ret += ", " + payee.ToString(); + ret += ", " + HexStr(payee); ret += ", " + std::to_string((int)vchSig.size()); return ret; } @@ -287,7 +287,7 @@ class CMasternodePayments ADD_SERIALIZE_METHODS; template - inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) + inline void SerializationOp(Stream& s, Operation ser_action) { READWRITE(mapMasternodePayeeVotes); READWRITE(mapMasternodeBlocks); diff --git a/src/masternode.cpp b/src/masternode.cpp index 7e9dcf1b3..bd9226218 100644 --- a/src/masternode.cpp +++ b/src/masternode.cpp @@ -75,7 +75,6 @@ CMasternode::CMasternode() : cacheInputAgeBlock = 0; unitTest = false; allowFreeTx = true; - nActiveState = MASTERNODE_ENABLED, protocolVersion = PROTOCOL_VERSION; nLastDsq = 0; nScanningErrorCount = 0; @@ -98,7 +97,6 @@ CMasternode::CMasternode(const CMasternode& other) : cacheInputAgeBlock = other.cacheInputAgeBlock; unitTest = other.unitTest; allowFreeTx = other.allowFreeTx; - nActiveState = MASTERNODE_ENABLED, protocolVersion = other.protocolVersion; nLastDsq = other.nLastDsq; nScanningErrorCount = other.nScanningErrorCount; @@ -210,16 +208,19 @@ void CMasternode::Check(bool forceCheck) } if (!unitTest) { + CValidationState state; + CMutableTransaction tx = CMutableTransaction(); + CScript dummyScript; + dummyScript << ToByteVector(pubKeyCollateralAddress) << OP_CHECKSIG; + CTxOut vout = CTxOut((GetMasterNodeCollateral(chainActive.Height()) - 0.01) * COIN, dummyScript); + tx.vin.push_back(vin); + tx.vout.push_back(vout); { TRY_LOCK(cs_main, lockMain); if (!lockMain) return; - CCoins coins; - if (!pcoinsTip->GetCoins(vin.prevout.hash, coins) || - (unsigned int)vin.prevout.n>=coins.vout.size() || - coins.vout[vin.prevout.n].IsNull()) { - nActiveState = MASTERNODE_OUTPOINT_SPENT; - LogPrint(BCLog::MASTERNODE, "CMasternode::Check -- Failed to find Masternode UTXO, masternode=%s\n", vin.prevout.ToStringShort()); + if (!AcceptableInputs(mempool, state, CTransaction(tx), false, NULL)) { + activeState = MASTERNODE_VIN_SPENT; return; } } @@ -294,30 +295,6 @@ int64_t CMasternode::GetLastPaid() return 0; } -std::string CMasternode::GetStatus() -{ - switch (nActiveState) { - case CMasternode::MASTERNODE_PRE_ENABLED: - return "PRE_ENABLED"; - case CMasternode::MASTERNODE_ENABLED: - return "ENABLED"; - case CMasternode::MASTERNODE_EXPIRED: - return "EXPIRED"; - case CMasternode::MASTERNODE_OUTPOINT_SPENT: - return "OUTPOINT_SPENT"; - case CMasternode::MASTERNODE_REMOVE: - return "REMOVE"; - case CMasternode::MASTERNODE_WATCHDOG_EXPIRED: - return "WATCHDOG_EXPIRED"; - case CMasternode::MASTERNODE_POSE_BAN: - return "POSE_BAN"; - case CMasternode::MASTERNODE_MISSING: - return "MISSING"; - default: - return "UNKNOWN"; - } -} - bool CMasternode::IsValidNetAddr() { // TODO: regtest is fine with any addresses for now, @@ -611,6 +588,14 @@ bool CMasternodeBroadcast::CheckInputsAndAdd(int& nDoS) mnodeman.Remove(pmn->vin); } + CValidationState state; + CMutableTransaction tx = CMutableTransaction(); + CScript dummyScript; + dummyScript << ToByteVector(pubKeyCollateralAddress) << OP_CHECKSIG; + CTxOut vout = CTxOut((GetMasterNodeCollateral(chainActive.Height()) - 0.01) * COIN, dummyScript); + tx.vin.push_back(vin); + tx.vout.push_back(vout); + { TRY_LOCK(cs_main, lockMain); if (!lockMain) { @@ -620,11 +605,9 @@ bool CMasternodeBroadcast::CheckInputsAndAdd(int& nDoS) return false; } - CCoins coins; - if (!pcoinsTip->GetCoins(vin.prevout.hash, coins) || - (unsigned int)vin.prevout.n>=coins.vout.size() || - coins.vout[vin.prevout.n].IsNull()) { - LogPrint(BCLog::MASTERNODE, "CMasternodeBroadcast::CheckInputsAndAdd -- Failed to find Masternode UTXO, masternode=%s\n", vin.prevout.ToStringShort()); + if (!AcceptableInputs(mempool, state, CTransaction(tx), false, NULL)) { + //set nDos + state.IsInvalid(nDoS); return false; } } @@ -761,21 +744,22 @@ bool CMasternodePing::CheckAndUpdate(int& nDos, bool fRequireEnabled, bool fChec return false; } + // Check if the ping block hash exists in disk BlockMap::iterator mi = mapBlockIndex.find(blockHash); - if (mi != mapBlockIndex.end() && (*mi).second) { - if ((*mi).second->nHeight < chainActive.Height() - 24) { - LogPrint(BCLog::MASTERNODE,"CMasternodePing::CheckAndUpdate - Masternode %s block hash %s is too old\n", vin.prevout.hash.ToString(), blockHash.ToString()); + if (mi == mapBlockIndex.end() || !(*mi).second) { + LogPrint(BCLog::MASTERNODE,"CMasternodePing::CheckAndUpdate - ping block not in disk. Masternode %s block hash %s\n", vin.prevout.hash.ToString(), blockHash.ToString()); + return false; + } + + // Verify ping block hash in main chain and in the [ tip > x > tip - 24 ] range. + { + LOCK(cs_main); + if (!chainActive.Contains((*mi).second) || (chainActive.Height() - (*mi).second->nHeight > 24)) { + LogPrint(BCLog::MASTERNODE,"CMasternodePing::CheckAndUpdate - Masternode %s block hash %s is too old or has an invalid block hash\n", vin.prevout.hash.ToString(), blockHash.ToString()); // Do nothing here (no Masternode update, no mnping relay) // Let this node to be visible but fail to accept mnping - return false; } - } else { - LogPrint(BCLog::MASTERNODE,"CMasternodePing::CheckAndUpdate - Masternode %s block hash %s is unknown\n", vin.prevout.hash.ToString(), blockHash.ToString()); - // maybe we stuck so we shouldn't ban this node, just fail to accept it - // TODO: or should we also request this block? - - return false; } pmn->lastPing = *this; diff --git a/src/masternode.h b/src/masternode.h index 39021a28d..c0407a6ae 100644 --- a/src/masternode.h +++ b/src/masternode.h @@ -49,7 +49,7 @@ class CMasternodePing : public CSignedMessage ADD_SERIALIZE_METHODS; template - inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) + inline void SerializationOp(Stream& s, Operation ser_action) { READWRITE(vin); READWRITE(blockHash); @@ -103,7 +103,7 @@ class CMasternodePing : public CSignedMessage }; // -// The Masternode Class. For managing the Obfuscation process. It contains the input of the 10000 AZR, signature to prove +// The Masternode Class. It contains the input of the 10000 AZR, signature to prove // it's the one who own that ip address and code for calculating the payment election. // class CMasternode : public CSignedMessage @@ -118,7 +118,6 @@ class CMasternode : public CSignedMessage MASTERNODE_PRE_ENABLED, MASTERNODE_ENABLED, MASTERNODE_EXPIRED, - MASTERNODE_OUTPOINT_SPENT, MASTERNODE_REMOVE, MASTERNODE_WATCHDOG_EXPIRED, MASTERNODE_POSE_BAN, @@ -140,7 +139,6 @@ class CMasternode : public CSignedMessage bool unitTest; bool allowFreeTx; int protocolVersion; - int nActiveState; int64_t nLastDsq; //the dsq count from the last dsq broadcast of this node int nScanningErrorCount; int nLastScanningErrorBlockHeight; @@ -200,7 +198,7 @@ class CMasternode : public CSignedMessage ADD_SERIALIZE_METHODS; template - inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) + inline void SerializationOp(Stream& s, Operation ser_action) { LOCK(cs); @@ -263,8 +261,6 @@ class CMasternode : public CSignedMessage return cacheInputAge + (chainActive.Tip()->nHeight - cacheInputAgeBlock); } - std::string GetStatus(); - std::string Status() { std::string strStatus = "ACTIVE"; @@ -313,7 +309,7 @@ class CMasternodeBroadcast : public CMasternode ADD_SERIALIZE_METHODS; template - inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) + inline void SerializationOp(Stream& s, Operation ser_action) { READWRITE(vin); READWRITE(addr); diff --git a/src/masternodeman.h b/src/masternodeman.h index 029f8469a..b2b3e8109 100644 --- a/src/masternodeman.h +++ b/src/masternodeman.h @@ -83,7 +83,7 @@ class CMasternodeMan ADD_SERIALIZE_METHODS; template - inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) + inline void SerializationOp(Stream& s, Operation ser_action) { LOCK(cs); READWRITE(vMasternodes); diff --git a/src/merkleblock.h b/src/merkleblock.h index 88cafa2ba..79ffadd31 100644 --- a/src/merkleblock.h +++ b/src/merkleblock.h @@ -86,7 +86,7 @@ class CPartialMerkleTree ADD_SERIALIZE_METHODS; template - inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) + inline void SerializationOp(Stream& s, Operation ser_action) { READWRITE(nTransactions); READWRITE(vHash); @@ -144,7 +144,7 @@ class CMerkleBlock ADD_SERIALIZE_METHODS; template - inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) + inline void SerializationOp(Stream& s, Operation ser_action) { READWRITE(header); READWRITE(txn); diff --git a/src/net.cpp b/src/net.cpp index bcbf26dce..e8ec3ec79 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -1472,71 +1472,77 @@ void ThreadOpenConnections() } } -void ThreadOpenAddedConnections() +std::vector GetAddedNodeInfo() { + std::vector ret; + + std::list lAddresses(0); { LOCK(cs_vAddedNodes); - vAddedNodes = mapMultiArgs["-addnode"]; + ret.reserve(vAddedNodes.size()); + for (std::string& strAddNode : vAddedNodes) + lAddresses.push_back(strAddNode); } - if (HaveNameProxy()) { - while (true) { - std::list lAddresses(0); - { - LOCK(cs_vAddedNodes); - for (std::string& strAddNode : vAddedNodes) - lAddresses.push_back(strAddNode); + + // Build a map of all already connected addresses (by IP:port and by name) to inbound/outbound and resolved CService + std::map mapConnected; + std::map > mapConnectedByName; + { + LOCK(cs_vNodes); + for (const CNode* pnode : vNodes) { + if (pnode->addr.IsValid()) { + mapConnected[pnode->addr] = pnode->fInbound; } - for (std::string& strAddNode : lAddresses) { - CAddress addr; - CSemaphoreGrant grant(*semOutbound); - OpenNetworkConnection(addr, false, &grant, strAddNode.c_str()); - MilliSleep(500); + if (!pnode->addrName.empty()) { + mapConnectedByName[pnode->addrName] = std::make_pair(pnode->fInbound, static_cast(pnode->addr)); } - MilliSleep(120000); // Retry every 2 minutes } } - for (unsigned int i = 0; true; i++) { - std::list lAddresses(0); - { - LOCK(cs_vAddedNodes); - for (std::string& strAddNode : vAddedNodes) - lAddresses.push_back(strAddNode); + for (std::string& strAddNode : lAddresses) { + CService service(strAddNode, Params().GetDefaultPort()); + if (service.IsValid()) { + // strAddNode is an IP:port + auto it = mapConnected.find(service); + if (it != mapConnected.end()) { + ret.push_back(AddedNodeInfo{strAddNode, service, true, it->second}); + } else { + ret.push_back(AddedNodeInfo{strAddNode, CService(), false, false}); + } + } else { + // strAddNode is a name + auto it = mapConnectedByName.find(strAddNode); + if (it != mapConnectedByName.end()) { + ret.push_back(AddedNodeInfo{strAddNode, it->second.second, true, it->second.first}); + } else { + ret.push_back(AddedNodeInfo{strAddNode, CService(), false, false}); + } } + } - std::list > lservAddressesToAdd(0); - for (std::string& strAddNode : lAddresses) { - std::vector vservNode(0); - if (Lookup(strAddNode.c_str(), vservNode, Params().GetDefaultPort(), fNameLookup, 0)) { - lservAddressesToAdd.push_back(vservNode); - { - LOCK(cs_setservAddNodeAddresses); - for (CService& serv : vservNode) - setservAddNodeAddresses.insert(serv); - } + return ret; +} + +void ThreadOpenAddedConnections() +{ + { + LOCK(cs_vAddedNodes); + vAddedNodes = mapMultiArgs["-addnode"]; + } + + for (unsigned int i = 0; true; i++) { + std::vector vInfo = GetAddedNodeInfo(); + for (const AddedNodeInfo& info : vInfo) { + if (!info.fConnected) { + CSemaphoreGrant grant(*semOutbound); + // If strAddedNode is an IP/port, decode it immediately, so + // OpenNetworkConnection can detect existing connections to that IP/port. + CService service(info.strAddedNode, Params().GetDefaultPort()); + OpenNetworkConnection(CAddress(service, NODE_NONE), false, &grant, info.strAddedNode.c_str(), false); + MilliSleep(500); } } - // Attempt to connect to each IP for each addnode entry until at least one is successful per addnode entry - // (keeping in mind that addnode entries can have many IPs if fNameLookup) - { - LOCK(cs_vNodes); - for (CNode* pnode : vNodes) - for (std::list >::iterator it = lservAddressesToAdd.begin(); it != lservAddressesToAdd.end(); it++) - for (CService& addrNode : *(it)) - if (pnode->addr == addrNode) { - it = lservAddressesToAdd.erase(it); - it--; - break; - } - } - for (std::vector& vserv : lservAddressesToAdd) { - CSemaphoreGrant grant(*semOutbound); - /* We want -addnode to work even for nodes that don't provide all - * wanted services, so pass in nServices=NODE_NONE to CAddress. */ - OpenNetworkConnection(CAddress(vserv[i % vserv.size()], NODE_NONE), false, &grant); - MilliSleep(500); - } MilliSleep(120000); // Retry every 2 minutes } } diff --git a/src/net.h b/src/net.h index bdf95732c..bcbcdea18 100644 --- a/src/net.h +++ b/src/net.h @@ -260,9 +260,8 @@ class CBanEntry ADD_SERIALIZE_METHODS; template - inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { - READWRITE(this->nVersion); - nVersion = this->nVersion; + inline void SerializationOp(Stream& s, Operation ser_action) { + READWRITE(nVersion); READWRITE(nCreateTime); READWRITE(nBanUntil); READWRITE(banReason); @@ -777,4 +776,13 @@ class CBanDB void DumpBanlist(); +struct AddedNodeInfo { + std::string strAddedNode; + CService resolvedAddress; + bool fConnected; + bool fInbound; +}; + +std::vector GetAddedNodeInfo(); + #endif // BITCOIN_NET_H diff --git a/src/netbase.cpp b/src/netbase.cpp index 20bcb0a12..ee58cecbb 100644 --- a/src/netbase.cpp +++ b/src/netbase.cpp @@ -641,10 +641,10 @@ bool ConnectSocketByName(CService& addr, SOCKET& hSocketRet, const char* pszDest proxyType nameProxy; GetNameProxy(nameProxy); - CService addrResolved; - if (Lookup(strDest.c_str(), addrResolved, port, fNameLookup && !HaveNameProxy())) { - if (addrResolved.IsValid()) { - addr = addrResolved; + std::vector addrResolved; + if (Lookup(strDest.c_str(), addrResolved, port, fNameLookup && !HaveNameProxy(), 256)) { + if (addrResolved.size() > 0) { + addr = addrResolved[GetRand(addrResolved.size())]; return ConnectSocket(addr, hSocketRet, nTimeout); } } diff --git a/src/netbase.h b/src/netbase.h index a43478964..eee3c1761 100644 --- a/src/netbase.h +++ b/src/netbase.h @@ -99,7 +99,7 @@ class CNetAddr ADD_SERIALIZE_METHODS; template - inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) + inline void SerializationOp(Stream& s, Operation ser_action) { READWRITE(FLATDATA(ip)); } @@ -136,7 +136,7 @@ class CSubNet ADD_SERIALIZE_METHODS; template - inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { + inline void SerializationOp(Stream& s, Operation ser_action) { READWRITE(network); READWRITE(FLATDATA(netmask)); READWRITE(FLATDATA(valid)); @@ -177,7 +177,7 @@ class CService : public CNetAddr ADD_SERIALIZE_METHODS; template - inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) + inline void SerializationOp(Stream& s, Operation ser_action) { READWRITE(FLATDATA(ip)); unsigned short portN = htons(port); diff --git a/src/primitives/block.h b/src/primitives/block.h index d59275857..0aa9757cd 100644 --- a/src/primitives/block.h +++ b/src/primitives/block.h @@ -40,9 +40,8 @@ class CBlockHeader ADD_SERIALIZE_METHODS; template - inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { - READWRITE(this->nVersion); - nVersion = this->nVersion; + inline void SerializationOp(Stream& s, Operation ser_action) { + READWRITE(nVersion); READWRITE(hashPrevBlock); READWRITE(hashMerkleRoot); READWRITE(nTime); @@ -106,7 +105,7 @@ class CBlock : public CBlockHeader ADD_SERIALIZE_METHODS; template - inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { + inline void SerializationOp(Stream& s, Operation ser_action) { READWRITE(*(CBlockHeader*)this); READWRITE(vtx); if(vtx.size() > 1 && vtx[1].IsCoinStake()) @@ -176,8 +175,9 @@ struct CBlockLocator ADD_SERIALIZE_METHODS; template - inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { - if (!(nType & SER_GETHASH)) + inline void SerializationOp(Stream& s, Operation ser_action) { + int nVersion = s.GetVersion(); + if (!(s.GetType() & SER_GETHASH)) READWRITE(nVersion); READWRITE(vHave); } diff --git a/src/primitives/transaction.cpp b/src/primitives/transaction.cpp index 2550c4293..3326488e1 100644 --- a/src/primitives/transaction.cpp +++ b/src/primitives/transaction.cpp @@ -67,7 +67,7 @@ std::string CTxIn::ToString() const else str += strprintf(", coinbase %s", HexStr(scriptSig)); else - str += strprintf(", scriptSig=%s", scriptSig.ToString().substr(0,24)); + str += strprintf(", scriptSig=%s", HexStr(scriptSig).substr(0, 24)); if (nSequence != std::numeric_limits::max()) str += strprintf(", nSequence=%u", nSequence); str += ")"; @@ -118,7 +118,7 @@ CAmount CTxOut::GetZerocoinMinted() const std::string CTxOut::ToString() const { - return strprintf("CTxOut(nValue=%d.%08d, scriptPubKey=%s)", nValue / COIN, nValue % COIN, scriptPubKey.ToString().substr(0,30)); + return strprintf("CTxOut(nValue=%d.%08d, scriptPubKey=%s)", nValue / COIN, nValue % COIN, HexStr(scriptPubKey).substr(0,30)); } CMutableTransaction::CMutableTransaction() : nVersion(CTransaction::CURRENT_VERSION), nLockTime(0) {} diff --git a/src/primitives/transaction.h b/src/primitives/transaction.h index 6223fad8b..78c1f7cea 100644 --- a/src/primitives/transaction.h +++ b/src/primitives/transaction.h @@ -29,7 +29,7 @@ class COutPoint ADD_SERIALIZE_METHODS; template - inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { + inline void SerializationOp(Stream& s, Operation ser_action) { READWRITE(hash); READWRITE(n); } @@ -82,7 +82,7 @@ class CTxIn ADD_SERIALIZE_METHODS; template - inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { + inline void SerializationOp(Stream& s, Operation ser_action) { READWRITE(prevout); READWRITE(*(CScriptBase*)(&scriptSig)); READWRITE(nSequence); @@ -131,7 +131,7 @@ class CTxOut ADD_SERIALIZE_METHODS; template - inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { + inline void SerializationOp(Stream& s, Operation ser_action) { READWRITE(nValue); READWRITE(*(CScriptBase*)(&scriptPubKey)); } @@ -171,7 +171,7 @@ class CTxOut // and that means that fee per txout is 182 * 10000 / 1000 = 1820 uazr. // So dust is a txout less than 1820 *3 = 5460 uazr // with default -minrelaytxfee = minRelayTxFee = 10000 uazr per kB. - size_t nSize = GetSerializeSize(SER_DISK,0)+148u; + size_t nSize = GetSerializeSize(*this, SER_DISK, 0) + 148u; return (nValue < 3*minRelayTxFee.GetFee(nSize)); } @@ -230,9 +230,8 @@ class CTransaction ADD_SERIALIZE_METHODS; template - inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { - READWRITE(*const_cast(&this->nVersion)); - nVersion = this->nVersion; + inline void SerializationOp(Stream& s, Operation ser_action) { + READWRITE(*const_cast(&nVersion)); READWRITE(*const_cast*>(&vin)); READWRITE(*const_cast*>(&vout)); READWRITE(*const_cast(&nLockTime)); @@ -314,9 +313,8 @@ struct CMutableTransaction ADD_SERIALIZE_METHODS; template - inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { - READWRITE(this->nVersion); - nVersion = this->nVersion; + inline void SerializationOp(Stream& s, Operation ser_action) { + READWRITE(nVersion); READWRITE(vin); READWRITE(vout); READWRITE(nLockTime); diff --git a/src/protocol.h b/src/protocol.h index 4be384af5..1ffbb0102 100644 --- a/src/protocol.h +++ b/src/protocol.h @@ -40,7 +40,7 @@ class CMessageHeader ADD_SERIALIZE_METHODS; template - inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) + inline void SerializationOp(Stream& s, Operation ser_action) { READWRITE(FLATDATA(pchMessageStart)); READWRITE(FLATDATA(pchCommand)); @@ -321,14 +321,15 @@ class CAddress : public CService ADD_SERIALIZE_METHODS; template - inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) + inline void SerializationOp(Stream& s, Operation ser_action) { if (ser_action.ForRead()) Init(); - if (nType & SER_DISK) + int nVersion = s.GetVersion(); + if (s.GetType() & SER_DISK) READWRITE(nVersion); - if ((nType & SER_DISK) || - (nVersion >= CADDR_TIME_VERSION && !(nType & SER_GETHASH))) + if ((s.GetType() & SER_DISK) || + (nVersion >= CADDR_TIME_VERSION && !(s.GetType() & SER_GETHASH))) READWRITE(nTime); uint64_t nServicesInt = nServices; READWRITE(nServicesInt); @@ -355,7 +356,7 @@ class CInv ADD_SERIALIZE_METHODS; template - inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) + inline void SerializationOp(Stream& s, Operation ser_action) { READWRITE(type); READWRITE(hash); diff --git a/src/pubkey.cpp b/src/pubkey.cpp index a1b05fad2..dc1b5db62 100644 --- a/src/pubkey.cpp +++ b/src/pubkey.cpp @@ -250,7 +250,7 @@ bool CPubKey::Derive(CPubKey& pubkeyChild, ChainCode &ccChild, unsigned int nChi return true; } -void CExtPubKey::Encode(unsigned char code[74]) const +void CExtPubKey::Encode(unsigned char code[BIP32_EXTKEY_SIZE]) const { code[0] = nDepth; memcpy(code+1, vchFingerprint, 4); @@ -261,7 +261,7 @@ void CExtPubKey::Encode(unsigned char code[74]) const memcpy(code+41, pubkey.begin(), CPubKey::COMPRESSED_PUBLIC_KEY_SIZE); } -void CExtPubKey::Decode(const unsigned char code[74]) +void CExtPubKey::Decode(const unsigned char code[BIP32_EXTKEY_SIZE]) { nDepth = code[0]; memcpy(vchFingerprint, code+1, 4); diff --git a/src/pubkey.h b/src/pubkey.h index 630c0c826..9e26861d5 100644 --- a/src/pubkey.h +++ b/src/pubkey.h @@ -122,19 +122,15 @@ class CPubKey } //! Implement serialization, as if this was a byte vector. - unsigned int GetSerializeSize(int nType, int nVersion) const - { - return size() + 1; - } template - void Serialize(Stream& s, int nType, int nVersion) const + void Serialize(Stream& s) const { unsigned int len = size(); ::WriteCompactSize(s, len); s.write((char*)vch, len); } template - void Unserialize(Stream& s, int nType, int nVersion) + void Unserialize(Stream& s) { unsigned int len = ::ReadCompactSize(s); if (len <= PUBLIC_KEY_SIZE) { diff --git a/src/qt/recentrequeststablemodel.h b/src/qt/recentrequeststablemodel.h index 2a68ddcdb..d925ec812 100644 --- a/src/qt/recentrequeststablemodel.h +++ b/src/qt/recentrequeststablemodel.h @@ -28,12 +28,11 @@ class RecentRequestEntry ADD_SERIALIZE_METHODS; template - inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) + inline void SerializationOp(Stream& s, Operation ser_action) { unsigned int nDate = date.toTime_t(); - READWRITE(this->nVersion); - nVersion = this->nVersion; + READWRITE(nVersion); READWRITE(id); READWRITE(nDate); READWRITE(recipient); diff --git a/src/qt/walletmodel.h b/src/qt/walletmodel.h index cd8f932db..29a318910 100644 --- a/src/qt/walletmodel.h +++ b/src/qt/walletmodel.h @@ -75,7 +75,7 @@ class SendCoinsRecipient ADD_SERIALIZE_METHODS; template - inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) + inline void SerializationOp(Stream& s, Operation ser_action) { std::string sAddress = address.toStdString(); std::string sLabel = label.toStdString(); @@ -86,7 +86,6 @@ class SendCoinsRecipient std::string sAuthenticatedMerchant = authenticatedMerchant.toStdString(); READWRITE(this->nVersion); - nVersion = this->nVersion; READWRITE(sAddress); READWRITE(sLabel); READWRITE(amount); diff --git a/src/rest.cpp b/src/rest.cpp index 2b3d4854a..ce0a625d8 100644 --- a/src/rest.cpp +++ b/src/rest.cpp @@ -49,7 +49,7 @@ struct CCoin { ADD_SERIALIZE_METHODS; template - inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) + inline void SerializationOp(Stream& s, Operation ser_action) { READWRITE(nTxVer); READWRITE(nHeight); diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 6fdfba9a3..0dbbc5d8d 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -600,8 +600,6 @@ UniValue gettxoutsetinfo(const UniValue& params, bool fHelp) "\nExamples:\n" + HelpExampleCli("gettxoutsetinfo", "") + HelpExampleRpc("gettxoutsetinfo", "")); - LOCK(cs_main); - UniValue ret(UniValue::VOBJ); CCoinsStats stats; @@ -1366,7 +1364,7 @@ UniValue getblockindexstats(const UniValue& params, bool fHelp) { nFees_all += nValueIn - nValueOut; if (!tx.HasZerocoinMintOutputs()) { nFees += nValueIn - nValueOut; - nBytes += tx.GetSerializeSize(SER_NETWORK, CLIENT_VERSION); + nBytes += GetSerializeSize(tx, SER_NETWORK, CLIENT_VERSION); } } diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp index 650035980..78890a765 100644 --- a/src/rpc/net.cpp +++ b/src/rpc/net.cpp @@ -238,27 +238,24 @@ UniValue getaddednodeinfo(const UniValue& params, bool fHelp) { if (fHelp || params.size() < 1 || params.size() > 2) throw std::runtime_error( - "getaddednodeinfo dns ( \"node\" )\n" + "getaddednodeinfo dummy ( \"node\" )\n" "\nReturns information about the given added node, or all added nodes\n" "(note that onetry addnodes are not listed here)\n" - "If dns is false, only a list of added nodes will be provided,\n" - "otherwise connected information will also be available.\n" "\nArguments:\n" - "1. dns (boolean, required) If false, only a list of added nodes will be provided, otherwise connected information will also be available.\n" + "1. dummy (boolean, required) Kept for historical purposes but ignored\n" "2. \"node\" (string, optional) If provided, return information about this specific node, otherwise all nodes are returned.\n" "\nResult:\n" "[\n" " {\n" - " \"addednode\" : \"192.168.0.201\", (string) The node ip address\n" + " \"addednode\" : \"192.168.0.201\", (string) The node ip address or name (as provided to addnode)\n" " \"connected\" : true|false, (boolean) If connected\n" - " \"addresses\" : [\n" + " \"addresses\" : [ (list of objects) Only when connected = true\n" " {\n" - " \"address\" : \"192.168.0.201:14725\", (string) The aezora server host and port\n" + " \"address\" : \"192.168.0.201:14725\", (string) The aezora server IP and port we're connected to\n" " \"connected\" : \"outbound\" (string) connection, inbound or outbound\n" " }\n" - " ,...\n" " ]\n" " }\n" " ,...\n" @@ -267,72 +264,35 @@ UniValue getaddednodeinfo(const UniValue& params, bool fHelp) "\nExamples:\n" + HelpExampleCli("getaddednodeinfo", "true") + HelpExampleCli("getaddednodeinfo", "true \"192.168.0.201\"") + HelpExampleRpc("getaddednodeinfo", "true, \"192.168.0.201\"")); - bool fDns = params[0].get_bool(); - - std::list laddedNodes(0); - if (params.size() == 1) { - LOCK(cs_vAddedNodes); - for (std::string& strAddNode : vAddedNodes) - laddedNodes.push_back(strAddNode); - } else { - std::string strNode = params[1].get_str(); - LOCK(cs_vAddedNodes); - for (std::string& strAddNode : vAddedNodes) - if (strAddNode == strNode) { - laddedNodes.push_back(strAddNode); + std::vector vInfo = GetAddedNodeInfo(); + + if (params.size() == 2) { + bool found = false; + for (const AddedNodeInfo& info : vInfo) { + if (info.strAddedNode == params[1].get_str()) { + vInfo.assign(1, info); + found = true; break; } - if (laddedNodes.size() == 0) + } + if (!found) { throw JSONRPCError(RPC_CLIENT_NODE_NOT_ADDED, "Error: Node has not been added."); - } - - UniValue ret(UniValue::VARR); - if (!fDns) { - for (std::string& strAddNode : laddedNodes) { - UniValue obj(UniValue::VOBJ); - obj.push_back(Pair("addednode", strAddNode)); - ret.push_back(obj); } - return ret; } - std::list > > laddedAddreses(0); - for (std::string& strAddNode : laddedNodes) { - std::vector vservNode(0); - if (Lookup(strAddNode.c_str(), vservNode, Params().GetDefaultPort(), fNameLookup, 0)) - laddedAddreses.push_back(std::make_pair(strAddNode, vservNode)); - else { - UniValue obj(UniValue::VOBJ); - obj.push_back(Pair("addednode", strAddNode)); - obj.push_back(Pair("connected", false)); - UniValue addresses(UniValue::VARR); - obj.push_back(Pair("addresses", addresses)); - } - } + UniValue ret(UniValue::VARR); - LOCK(cs_vNodes); - for (std::list > >::iterator it = laddedAddreses.begin(); it != laddedAddreses.end(); it++) { + for (const AddedNodeInfo& info : vInfo) { UniValue obj(UniValue::VOBJ); - obj.push_back(Pair("addednode", it->first)); - + obj.push_back(Pair("addednode", info.strAddedNode)); + obj.push_back(Pair("connected", info.fConnected)); UniValue addresses(UniValue::VARR); - bool fConnected = false; - for (CService& addrNode : it->second) { - bool fFound = false; - UniValue node(UniValue::VOBJ); - node.push_back(Pair("address", addrNode.ToString())); - for (CNode* pnode : vNodes) - if (pnode->addr == addrNode) { - fFound = true; - fConnected = true; - node.push_back(Pair("connected", pnode->fInbound ? "inbound" : "outbound")); - break; - } - if (!fFound) - node.push_back(Pair("connected", "false")); - addresses.push_back(node); + if (info.fConnected) { + UniValue address(UniValue::VOBJ); + address.push_back(Pair("address", info.resolvedAddress.ToString())); + address.push_back(Pair("connected", info.fInbound ? "inbound" : "outbound")); + addresses.push_back(address); } - obj.push_back(Pair("connected", fConnected)); obj.push_back(Pair("addresses", addresses)); ret.push_back(obj); } diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index dbe75f03b..e57be27f9 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -39,7 +39,7 @@ void ScriptPubKeyToJSON(const CScript& scriptPubKey, UniValue& out, bool fInclud std::vector addresses; int nRequired; - out.push_back(Pair("asm", scriptPubKey.ToString())); + out.push_back(Pair("asm", ScriptToAsmStr(scriptPubKey))); if (fIncludeHex) out.push_back(Pair("hex", HexStr(scriptPubKey.begin(), scriptPubKey.end()))); @@ -714,8 +714,8 @@ UniValue signrawtransaction(const UniValue& params, bool fHelp) CCoinsModifier coins = view.ModifyCoins(txid); if (coins->IsAvailable(nOut) && coins->vout[nOut].scriptPubKey != scriptPubKey) { std::string err("Previous output scriptPubKey mismatch:\n"); - err = err + coins->vout[nOut].scriptPubKey.ToString() + "\nvs:\n" + - scriptPubKey.ToString(); + err = err + ScriptToAsmStr(coins->vout[nOut].scriptPubKey) + "\nvs:\n"+ + ScriptToAsmStr(scriptPubKey); throw JSONRPCError(RPC_DESERIALIZATION_ERROR, err); } if ((unsigned int)nOut >= coins->vout.size()) diff --git a/src/script/bitcoinconsensus.cpp b/src/script/bitcoinconsensus.cpp index dec109786..9673477d2 100644 --- a/src/script/bitcoinconsensus.cpp +++ b/src/script/bitcoinconsensus.cpp @@ -23,7 +23,7 @@ class TxInputStream m_remaining(txToLen) {} - TxInputStream& read(char* pch, size_t nSize) + void read(char* pch, size_t nSize) { if (nSize > m_remaining) throw std::ios_base::failure(std::string(__func__) + ": end of data"); @@ -37,16 +37,18 @@ class TxInputStream memcpy(pch, m_data, nSize); m_remaining -= nSize; m_data += nSize; - return *this; } template TxInputStream& operator>>(T& obj) { - ::Unserialize(*this, obj, m_type, m_version); + ::Unserialize(*this, obj); return *this; } + int GetVersion() const { return m_version; } + int GetType() const { return m_type; } + private: const int m_type; const int m_version; @@ -80,7 +82,7 @@ int bitcoinconsensus_verify_script(const unsigned char *scriptPubKey, unsigned i stream >> tx; if (nIn >= tx.vin.size()) return set_error(err, bitcoinconsensus_ERR_TX_INDEX); - if (tx.GetSerializeSize(SER_NETWORK, PROTOCOL_VERSION) != txToLen) + if (GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION) != txToLen) return set_error(err, bitcoinconsensus_ERR_TX_SIZE_MISMATCH); // Regardless of the verification result, the tx did not error. diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp index 9e5d0753d..7c06d378e 100644 --- a/src/script/interpreter.cpp +++ b/src/script/interpreter.cpp @@ -188,7 +188,7 @@ bool static IsDefinedHashtypeSignature(const valtype &vchSig) { return true; } -bool static CheckSignatureEncoding(const valtype &vchSig, unsigned int flags, ScriptError* serror) { +bool CheckSignatureEncoding(const std::vector &vchSig, unsigned int flags, ScriptError* serror) { // Empty signature. Not strictly DER encoded, but allowed to provide a // compact way to provide an invalid signature for use with CHECK(MULTI)SIG if (vchSig.size() == 0) { @@ -1012,7 +1012,7 @@ class CTransactionSignatureSerializer { /** Serialize the passed scriptCode, skipping OP_CODESEPARATORs */ template - void SerializeScriptCode(S &s, int nType, int nVersion) const { + void SerializeScriptCode(S &s) const { CScript::const_iterator it = scriptCode.begin(); CScript::const_iterator itBegin = it; opcodetype opcode; @@ -1035,53 +1035,53 @@ class CTransactionSignatureSerializer { /** Serialize an input of txTo */ template - void SerializeInput(S &s, unsigned int nInput, int nType, int nVersion) const { + void SerializeInput(S &s, unsigned int nInput) const { // In case of SIGHASH_ANYONECANPAY, only the input being signed is serialized if (fAnyoneCanPay) nInput = nIn; // Serialize the prevout - ::Serialize(s, txTo.vin[nInput].prevout, nType, nVersion); + ::Serialize(s, txTo.vin[nInput].prevout); // Serialize the script if (nInput != nIn) // Blank out other inputs' signatures - ::Serialize(s, CScriptBase(), nType, nVersion); + ::Serialize(s, CScriptBase()); else - SerializeScriptCode(s, nType, nVersion); + SerializeScriptCode(s); // Serialize the nSequence if (nInput != nIn && (fHashSingle || fHashNone)) // let the others update at will - ::Serialize(s, (int)0, nType, nVersion); + ::Serialize(s, (int)0); else - ::Serialize(s, txTo.vin[nInput].nSequence, nType, nVersion); + ::Serialize(s, txTo.vin[nInput].nSequence); } /** Serialize an output of txTo */ template - void SerializeOutput(S &s, unsigned int nOutput, int nType, int nVersion) const { + void SerializeOutput(S &s, unsigned int nOutput) const { if (fHashSingle && nOutput != nIn) // Do not lock-in the txout payee at other indices as txin - ::Serialize(s, CTxOut(), nType, nVersion); + ::Serialize(s, CTxOut()); else - ::Serialize(s, txTo.vout[nOutput], nType, nVersion); + ::Serialize(s, txTo.vout[nOutput]); } /** Serialize txTo */ template - void Serialize(S &s, int nType, int nVersion) const { + void Serialize(S &s) const { // Serialize nVersion - ::Serialize(s, txTo.nVersion, nType, nVersion); + ::Serialize(s, txTo.nVersion); // Serialize vin unsigned int nInputs = fAnyoneCanPay ? 1 : txTo.vin.size(); ::WriteCompactSize(s, nInputs); for (unsigned int nInput = 0; nInput < nInputs; nInput++) - SerializeInput(s, nInput, nType, nVersion); + SerializeInput(s, nInput); // Serialize vout unsigned int nOutputs = fHashNone ? 0 : (fHashSingle ? nIn+1 : txTo.vout.size()); ::WriteCompactSize(s, nOutputs); for (unsigned int nOutput = 0; nOutput < nOutputs; nOutput++) - SerializeOutput(s, nOutput, nType, nVersion); + SerializeOutput(s, nOutput); // Serialize nLockTime - ::Serialize(s, txTo.nLockTime, nType, nVersion); + ::Serialize(s, txTo.nLockTime); } }; diff --git a/src/script/interpreter.h b/src/script/interpreter.h index 1a86baabf..c78836246 100644 --- a/src/script/interpreter.h +++ b/src/script/interpreter.h @@ -84,6 +84,8 @@ enum SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY = (1U << 9) }; +bool CheckSignatureEncoding(const std::vector &vchSig, unsigned int flags, ScriptError* serror); + uint256 SignatureHash(const CScript &scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType); class BaseSignatureChecker diff --git a/src/script/keyorigin.h b/src/script/keyorigin.h index e48ab2b23..a03c74cf5 100644 --- a/src/script/keyorigin.h +++ b/src/script/keyorigin.h @@ -20,7 +20,7 @@ struct KeyOriginInfo ADD_SERIALIZE_METHODS; template - inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) + inline void SerializationOp(Stream& s, Operation ser_action) { READWRITE(FLATDATA(fingerprint)); READWRITE(path); diff --git a/src/script/script.cpp b/src/script/script.cpp index 26e19ae54..e62a947e7 100644 --- a/src/script/script.cpp +++ b/src/script/script.cpp @@ -8,16 +8,6 @@ #include "tinyformat.h" #include "utilstrencodings.h" -namespace { -inline std::string ValueString(const std::vector& vch) -{ - if (vch.size() <= 4) - return strprintf("%d", CScriptNum(vch, false).getint()); - else - return HexStr(vch); -} -} // anon namespace - const char* GetOpName(opcodetype opcode) { @@ -304,32 +294,3 @@ bool CScript::IsPushOnly() const { return this->IsPushOnly(begin()); } - -std::string CScript::ToString() const -{ - std::string str; - opcodetype opcode; - std::vector vch; - const_iterator pc = begin(); - while (pc < end()) - { - if (!str.empty()) - str += " "; - if (!GetOp(pc, opcode, vch)) - { - str += "[error]"; - return str; - } - if (0 <= opcode && opcode <= OP_PUSHDATA4) { - str += ValueString(vch); - } else { - str += GetOpName(opcode); - if (opcode == OP_ZEROCOINSPEND) { - //Zerocoinspend has no further op codes. - break; - } - } - - } - return str; -} diff --git a/src/script/script.h b/src/script/script.h index adc3308a2..29f55b4b0 100644 --- a/src/script/script.h +++ b/src/script/script.h @@ -646,7 +646,6 @@ class CScript : public CScriptBase return (size() > 0 && *begin() == OP_RETURN) || (size() > MAX_SCRIPT_SIZE); } - std::string ToString() const; void clear() { // The default prevector::clear() does not release memory diff --git a/src/serialize.h b/src/serialize.h index 967a0bc22..c9f2bfa45 100644 --- a/src/serialize.h +++ b/src/serialize.h @@ -155,6 +155,8 @@ inline float ser_uint32_to_float(uint32_t y) // i.e. anything that supports .read(char*, size_t) and .write(char*, size_t) // +class CSizeComputer; + enum { // primary actions SER_NETWORK = (1 << 0), @@ -162,7 +164,7 @@ enum { SER_GETHASH = (1 << 2), }; -#define READWRITE(obj) (::SerReadWrite(s, (obj), nType, nVersion, ser_action)) +#define READWRITE(obj) (::SerReadWrite(s, (obj), ser_action)) /** * Implement three methods for serializable objects. These are actually wrappers over @@ -171,110 +173,88 @@ enum { * added as members. */ #define ADD_SERIALIZE_METHODS \ - size_t GetSerializeSize(int nType, int nVersion) const \ - { \ - CSizeComputer s(nType, nVersion); \ - NCONST_PTR(this)->SerializationOp(s, CSerActionSerialize(), nType, nVersion); \ - return s.size(); \ - } \ template \ - void Serialize(Stream& s, int nType, int nVersion) const \ + void Serialize(Stream& s) const \ { \ - NCONST_PTR(this)->SerializationOp(s, CSerActionSerialize(), nType, nVersion); \ + NCONST_PTR(this)->SerializationOp(s, CSerActionSerialize()); \ } \ template \ - void Unserialize(Stream& s, int nType, int nVersion) \ + void Unserialize(Stream& s) \ { \ - SerializationOp(s, CSerActionUnserialize(), nType, nVersion); \ + SerializationOp(s, CSerActionUnserialize()); \ } /* * Basic Types */ -inline unsigned int GetSerializeSize(char a, int, int=0) { return 1; } -inline unsigned int GetSerializeSize(int8_t a, int, int=0) { return 1; } -inline unsigned int GetSerializeSize(uint8_t a, int, int=0) { return 1; } -inline unsigned int GetSerializeSize(int16_t a, int, int=0) { return 2; } -inline unsigned int GetSerializeSize(uint16_t a, int, int=0) { return 2; } -inline unsigned int GetSerializeSize(int32_t a, int, int=0) { return 4; } -inline unsigned int GetSerializeSize(uint32_t a, int, int=0) { return 4; } -inline unsigned int GetSerializeSize(int64_t a, int, int=0) { return 8; } -inline unsigned int GetSerializeSize(uint64_t a, int, int=0) { return 8; } -inline unsigned int GetSerializeSize(float a, int, int=0) { return 4; } -inline unsigned int GetSerializeSize(double a, int, int=0) { return 8; } - -template inline void Serialize(Stream& s, char a, int, int=0) { ser_writedata8(s, a); } // TODO Get rid of bare char -template inline void Serialize(Stream& s, int8_t a, int, int=0) { ser_writedata8(s, a); } -template inline void Serialize(Stream& s, uint8_t a, int, int=0) { ser_writedata8(s, a); } -template inline void Serialize(Stream& s, int16_t a, int, int=0) { ser_writedata16(s, a); } -template inline void Serialize(Stream& s, uint16_t a, int, int=0) { ser_writedata16(s, a); } -template inline void Serialize(Stream& s, int32_t a, int, int=0) { ser_writedata32(s, a); } -template inline void Serialize(Stream& s, uint32_t a, int, int=0) { ser_writedata32(s, a); } -template inline void Serialize(Stream& s, int64_t a, int, int=0) { ser_writedata64(s, a); } -template inline void Serialize(Stream& s, uint64_t a, int, int=0) { ser_writedata64(s, a); } -template inline void Serialize(Stream& s, float a, int, int=0) { ser_writedata32(s, ser_float_to_uint32(a)); } -template inline void Serialize(Stream& s, double a, int, int=0) { ser_writedata64(s, ser_double_to_uint64(a)); } - -template inline void Unserialize(Stream& s, char& a, int, int=0) { a = ser_readdata8(s); } // TODO Get rid of bare char -template inline void Unserialize(Stream& s, int8_t& a, int, int=0) { a = ser_readdata8(s); } -template inline void Unserialize(Stream& s, uint8_t& a, int, int=0) { a = ser_readdata8(s); } -template inline void Unserialize(Stream& s, int16_t& a, int, int=0) { a = ser_readdata16(s); } -template inline void Unserialize(Stream& s, uint16_t& a, int, int=0) { a = ser_readdata16(s); } -template inline void Unserialize(Stream& s, int32_t& a, int, int=0) { a = ser_readdata32(s); } -template inline void Unserialize(Stream& s, uint32_t& a, int, int=0) { a = ser_readdata32(s); } -template inline void Unserialize(Stream& s, int64_t& a, int, int=0) { a = ser_readdata64(s); } -template inline void Unserialize(Stream& s, uint64_t& a, int, int=0) { a = ser_readdata64(s); } -template inline void Unserialize(Stream& s, float& a, int, int=0) { a = ser_uint32_to_float(ser_readdata32(s)); } -template inline void Unserialize(Stream& s, double& a, int, int=0) { a = ser_uint64_to_double(ser_readdata64(s)); } - -inline unsigned int GetSerializeSize(bool a, int, int = 0) { return sizeof(char); } -template inline void Serialize(Stream& s, bool a, int, int=0) { char f=a; ser_writedata8(s, f); } -template inline void Unserialize(Stream& s, bool& a, int, int=0) { char f=ser_readdata8(s); a=f; } +template inline void Serialize(Stream& s, char a ) { ser_writedata8(s, a); } // TODO Get rid of bare char +template inline void Serialize(Stream& s, int8_t a ) { ser_writedata8(s, a); } +template inline void Serialize(Stream& s, uint8_t a ) { ser_writedata8(s, a); } +template inline void Serialize(Stream& s, int16_t a ) { ser_writedata16(s, a); } +template inline void Serialize(Stream& s, uint16_t a) { ser_writedata16(s, a); } +template inline void Serialize(Stream& s, int32_t a ) { ser_writedata32(s, a); } +template inline void Serialize(Stream& s, uint32_t a) { ser_writedata32(s, a); } +template inline void Serialize(Stream& s, int64_t a ) { ser_writedata64(s, a); } +template inline void Serialize(Stream& s, uint64_t a) { ser_writedata64(s, a); } +template inline void Serialize(Stream& s, float a ) { ser_writedata32(s, ser_float_to_uint32(a)); } +template inline void Serialize(Stream& s, double a ) { ser_writedata64(s, ser_double_to_uint64(a)); } + +template inline void Unserialize(Stream& s, char& a ) { a = ser_readdata8(s); } // TODO Get rid of bare char +template inline void Unserialize(Stream& s, int8_t& a ) { a = ser_readdata8(s); } +template inline void Unserialize(Stream& s, uint8_t& a ) { a = ser_readdata8(s); } +template inline void Unserialize(Stream& s, int16_t& a ) { a = ser_readdata16(s); } +template inline void Unserialize(Stream& s, uint16_t& a) { a = ser_readdata16(s); } +template inline void Unserialize(Stream& s, int32_t& a ) { a = ser_readdata32(s); } +template inline void Unserialize(Stream& s, uint32_t& a) { a = ser_readdata32(s); } +template inline void Unserialize(Stream& s, int64_t& a ) { a = ser_readdata64(s); } +template inline void Unserialize(Stream& s, uint64_t& a) { a = ser_readdata64(s); } +template inline void Unserialize(Stream& s, float& a ) { a = ser_uint32_to_float(ser_readdata32(s)); } +template inline void Unserialize(Stream& s, double& a ) { a = ser_uint64_to_double(ser_readdata64(s)); } + +template inline void Serialize(Stream& s, bool a) { char f=a; ser_writedata8(s, f); } +template inline void Unserialize(Stream& s, bool& a) { char f=ser_readdata8(s); a=f; } // Serializatin for libzerocoin::CoinDenomination -inline unsigned int GetSerializeSize(libzerocoin::CoinDenomination a, int, int = 0) { return sizeof(libzerocoin::CoinDenomination); } template -inline void Serialize(Stream& s, libzerocoin::CoinDenomination a, int, int = 0) +inline void Serialize(Stream& s, libzerocoin::CoinDenomination a) { int f = libzerocoin::ZerocoinDenominationToInt(a); ser_writedata32(s, f); } template -inline void Unserialize(Stream& s, libzerocoin::CoinDenomination& a, int, int = 0) +inline void Unserialize(Stream& s, libzerocoin::CoinDenomination& a) { int f = ser_readdata32(s); a = libzerocoin::IntToZerocoinDenomination(f); } // Serialization for libzerocoin::SpendType -inline unsigned int GetSerializedSize(libzerocoin::SpendType a, int, int = 0) { return sizeof(libzerocoin::SpendType); } template -inline void Serialize(Stream& s, libzerocoin::SpendType a, int, int = 0) +inline void Serialize(Stream& s, libzerocoin::SpendType a) { uint8_t f = static_cast(a); ser_writedata8(s, f); } template -inline void Unserialize(Stream& s, libzerocoin::SpendType & a, int, int = 0) +inline void Unserialize(Stream& s, libzerocoin::SpendType & a) { uint8_t f = ser_readdata8(s); a = static_cast(f); } // Serialization for SporkId -inline unsigned int GetSerializeSize(SporkId sporkID, int, int = 0) { return sizeof(SporkId); } template -inline void Serialize(Stream& s, SporkId sporkID, int, int = 0) +inline void Serialize(Stream& s, SporkId sporkID) { int32_t f = static_cast(sporkID); ser_writedata32(s, f); } template -inline void Unserialize(Stream& s, SporkId& sporkID, int, int = 0) +inline void Unserialize(Stream& s, SporkId& sporkID) { int32_t f = ser_readdata32(s); sporkID = (SporkId) f; @@ -300,6 +280,8 @@ inline unsigned int GetSizeOfCompactSize(uint64_t nSize) return sizeof(unsigned char) + sizeof(uint64_t); } +inline void WriteCompactSize(CSizeComputer& os, uint64_t nSize); + template void WriteCompactSize(Stream& os, uint64_t nSize) { @@ -380,6 +362,9 @@ inline unsigned int GetSizeOfVarInt(I n) return nRet; } +template +inline void WriteVarInt(CSizeComputer& os, I n); + template void WriteVarInt(Stream& os, I n) { @@ -413,6 +398,7 @@ I ReadVarInt(Stream& is) #define FLATDATA(obj) REF(CFlatData((char*)&(obj), (char*)&(obj) + sizeof(obj))) #define VARINT(obj) REF(WrapVarInt(REF(obj))) +#define COMPACTSIZE(obj) REF(CCompactSize(REF(obj))) #define LIMITED_STRING(obj, n) REF(LimitedString(REF(obj))) /** @@ -443,19 +429,14 @@ class CFlatData char* end() { return pend; } const char* end() const { return pend; } - unsigned int GetSerializeSize(int, int = 0) const - { - return pend - pbegin; - } - template - void Serialize(Stream& s, int, int = 0) const + void Serialize(Stream& s) const { s.write(pbegin, pend - pbegin); } template - void Unserialize(Stream& s, int, int = 0) + void Unserialize(Stream& s) { s.read(pbegin, pend - pbegin); } @@ -470,24 +451,37 @@ class CVarInt public: CVarInt(I& nIn) : n(nIn) {} - unsigned int GetSerializeSize(int, int) const - { - return GetSizeOfVarInt(n); - } - template - void Serialize(Stream& s, int, int) const + void Serialize(Stream& s) const { WriteVarInt(s, n); } template - void Unserialize(Stream& s, int, int) + void Unserialize(Stream& s) { n = ReadVarInt(s); } }; +class CCompactSize +{ +protected: + uint64_t &n; +public: + CCompactSize(uint64_t& nIn) : n(nIn) { } + + template + void Serialize(Stream &s) const { + WriteCompactSize(s, n); + } + + template + void Unserialize(Stream& s) { + n = ReadCompactSize(s); + } +}; + template class LimitedString { @@ -495,10 +489,10 @@ class LimitedString std::string& string; public: - LimitedString(std::string& string) : string(string) {} + LimitedString(std::string& _string) : string(_string) {} template - void Unserialize(Stream& s, int, int = 0) + void Unserialize(Stream& s) { size_t size = ReadCompactSize(s); if (size > Limit) { @@ -510,17 +504,12 @@ class LimitedString } template - void Serialize(Stream& s, int, int = 0) const + void Serialize(Stream& s) const { WriteCompactSize(s, string.size()); if (!string.empty()) s.write((char*)&string[0], string.size()); } - - unsigned int GetSerializeSize(int, int = 0) const - { - return GetSizeOfCompactSize(string.size()) + string.size(); - } }; template @@ -536,117 +525,71 @@ CVarInt WrapVarInt(I& n) /** * std::string */ -template -unsigned int GetSerializeSize(const std::basic_string& str, int, int = 0); -template -void Serialize(Stream& os, const std::basic_string& str, int, int = 0); -template -void Unserialize(Stream& is, std::basic_string& str, int, int = 0); +template void Serialize(Stream& os, const std::basic_string& str); +template void Unserialize(Stream& is, std::basic_string& str); /** * prevector * prevectors of unsigned char are a special case and are intended to be serialized as a single opaque blob. */ -template unsigned int GetSerializeSize_impl(const prevector& v, int nType, int nVersion, const unsigned char&); -template unsigned int GetSerializeSize_impl(const prevector& v, int nType, int nVersion, const V&); -template inline unsigned int GetSerializeSize(const prevector& v, int nType, int nVersion); -template void Serialize_impl(Stream& os, const prevector& v, int nType, int nVersion, const unsigned char&); -template void Serialize_impl(Stream& os, const prevector& v, int nType, int nVersion, const V&); -template inline void Serialize(Stream& os, const prevector& v, int nType, int nVersion); -template void Unserialize_impl(Stream& is, prevector& v, int nType, int nVersion, const unsigned char&); -template void Unserialize_impl(Stream& is, prevector& v, int nType, int nVersion, const V&); -template inline void Unserialize(Stream& is, prevector& v, int nType, int nVersion); +template void Serialize_impl(Stream& os, const prevector& v, const unsigned char&); +template void Serialize_impl(Stream& os, const prevector& v, const V&); +template inline void Serialize(Stream& os, const prevector& v); +template void Unserialize_impl(Stream& is, prevector& v, const unsigned char&); +template void Unserialize_impl(Stream& is, prevector& v, const V&); +template inline void Unserialize(Stream& is, prevector& v); /** * vector * vectors of unsigned char are a special case and are intended to be serialized as a single opaque blob. */ -template -unsigned int GetSerializeSize_impl(const std::vector& v, int nType, int nVersion, const unsigned char&); -template -unsigned int GetSerializeSize_impl(const std::vector& v, int nType, int nVersion, const V&); -template -inline unsigned int GetSerializeSize(const std::vector& v, int nType, int nVersion); -template -void Serialize_impl(Stream& os, const std::vector& v, int nType, int nVersion, const unsigned char&); -template -void Serialize_impl(Stream& os, const std::vector& v, int nType, int nVersion, const V&); -template -inline void Serialize(Stream& os, const std::vector& v, int nType, int nVersion); -template -void Unserialize_impl(Stream& is, std::vector& v, int nType, int nVersion, const unsigned char&); -template -void Unserialize_impl(Stream& is, std::vector& v, int nType, int nVersion, const V&); -template -inline void Unserialize(Stream& is, std::vector& v, int nType, int nVersion); +template void Serialize_impl(Stream& os, const std::vector& v, const unsigned char&); +template void Serialize_impl(Stream& os, const std::vector& v, const V&); +template inline void Serialize(Stream& os, const std::vector& v); +template void Unserialize_impl(Stream& is, std::vector& v, const unsigned char&); +template void Unserialize_impl(Stream& is, std::vector& v, const V&); +template inline void Unserialize(Stream& is, std::vector& v); /** * pair */ -template -unsigned int GetSerializeSize(const std::pair& item, int nType, int nVersion); -template -void Serialize(Stream& os, const std::pair& item, int nType, int nVersion); -template -void Unserialize(Stream& is, std::pair& item, int nType, int nVersion); +template void Serialize(Stream& os, const std::pair& item); +template void Unserialize(Stream& is, std::pair& item); /** * map */ -template -unsigned int GetSerializeSize(const std::map& m, int nType, int nVersion); -template -void Serialize(Stream& os, const std::map& m, int nType, int nVersion); -template -void Unserialize(Stream& is, std::map& m, int nType, int nVersion); +template void Serialize(Stream& os, const std::map& m); +template void Unserialize(Stream& is, std::map& m); /** * set */ -template -unsigned int GetSerializeSize(const std::set& m, int nType, int nVersion); -template -void Serialize(Stream& os, const std::set& m, int nType, int nVersion); -template -void Unserialize(Stream& is, std::set& m, int nType, int nVersion); +template void Serialize(Stream& os, const std::set& m); +template void Unserialize(Stream& is, std::set& m); /** * If none of the specialized versions above matched, default to calling member function. - * "int nType" is changed to "long nType" to keep from getting an ambiguous overload error. - * The compiler will only cast int to long if none of the other templates matched. - * Thanks to Boost serialization for this idea. */ -template -inline unsigned int GetSerializeSize(const T& a, long nType, int nVersion) -{ - return a.GetSerializeSize((int)nType, nVersion); -} - template -inline void Serialize(Stream& os, const T& a, long nType, int nVersion) +inline void Serialize(Stream& os, const T& a) { - a.Serialize(os, (int)nType, nVersion); + a.Serialize(os); } template -inline void Unserialize(Stream& is, T& a, long nType, int nVersion) +inline void Unserialize(Stream& is, T& a) { - a.Unserialize(is, (int)nType, nVersion); + a.Unserialize(is); } /** * string */ -template -unsigned int GetSerializeSize(const std::basic_string& str, int, int) -{ - return GetSizeOfCompactSize(str.size()) + str.size() * sizeof(str[0]); -} - template -void Serialize(Stream& os, const std::basic_string& str, int, int) +void Serialize(Stream& os, const std::basic_string& str) { WriteCompactSize(os, str.size()); if (!str.empty()) @@ -654,7 +597,7 @@ void Serialize(Stream& os, const std::basic_string& str, int, int) } template -void Unserialize(Stream& is, std::basic_string& str, int, int) +void Unserialize(Stream& is, std::basic_string& str) { unsigned int nSize = ReadCompactSize(is); str.resize(nSize); @@ -667,30 +610,8 @@ void Unserialize(Stream& is, std::basic_string& str, int, int) /** * prevector */ -template -unsigned int GetSerializeSize_impl(const prevector& v, int nType, int nVersion, const unsigned char&) -{ - return (GetSizeOfCompactSize(v.size()) + v.size() * sizeof(T)); -} - -template -unsigned int GetSerializeSize_impl(const prevector& v, int nType, int nVersion, const V&) -{ - unsigned int nSize = GetSizeOfCompactSize(v.size()); - for (typename prevector::const_iterator vi = v.begin(); vi != v.end(); ++vi) - nSize += GetSerializeSize((*vi), nType, nVersion); - return nSize; -} - -template -inline unsigned int GetSerializeSize(const prevector& v, int nType, int nVersion) -{ - return GetSerializeSize_impl(v, nType, nVersion, T()); -} - - template -void Serialize_impl(Stream& os, const prevector& v, int nType, int nVersion, const unsigned char&) +void Serialize_impl(Stream& os, const prevector& v, const unsigned char&) { WriteCompactSize(os, v.size()); if (!v.empty()) @@ -698,22 +619,22 @@ void Serialize_impl(Stream& os, const prevector& v, int nType, int nVersio } template -void Serialize_impl(Stream& os, const prevector& v, int nType, int nVersion, const V&) +void Serialize_impl(Stream& os, const prevector& v, const V&) { WriteCompactSize(os, v.size()); for (typename prevector::const_iterator vi = v.begin(); vi != v.end(); ++vi) - ::Serialize(os, (*vi), nType, nVersion); + ::Serialize(os, (*vi)); } template -inline void Serialize(Stream& os, const prevector& v, int nType, int nVersion) +inline void Serialize(Stream& os, const prevector& v) { - Serialize_impl(os, v, nType, nVersion, T()); + Serialize_impl(os, v, T()); } template -void Unserialize_impl(Stream& is, prevector& v, int nType, int nVersion, const unsigned char&) +void Unserialize_impl(Stream& is, prevector& v, const unsigned char&) { // Limit size per read so bogus size value won't cause out of memory v.clear(); @@ -729,7 +650,7 @@ void Unserialize_impl(Stream& is, prevector& v, int nType, int nVersion, c } template -void Unserialize_impl(Stream& is, prevector& v, int nType, int nVersion, const V&) +void Unserialize_impl(Stream& is, prevector& v, const V&) { v.clear(); unsigned int nSize = ReadCompactSize(is); @@ -742,14 +663,14 @@ void Unserialize_impl(Stream& is, prevector& v, int nType, int nVersion, c nMid = nSize; v.resize(nMid); for (; i < nMid; i++) - Unserialize(is, v[i], nType, nVersion); + Unserialize(is, v[i]); } } template -inline void Unserialize(Stream& is, prevector& v, int nType, int nVersion) +inline void Unserialize(Stream& is, prevector& v) { - Unserialize_impl(is, v, nType, nVersion, T()); + Unserialize_impl(is, v, T()); } @@ -757,30 +678,8 @@ inline void Unserialize(Stream& is, prevector& v, int nType, int nVersion) /** * vector */ -template -unsigned int GetSerializeSize_impl(const std::vector& v, int nType, int nVersion, const unsigned char&) -{ - return (GetSizeOfCompactSize(v.size()) + v.size() * sizeof(T)); -} - -template -unsigned int GetSerializeSize_impl(const std::vector& v, int nType, int nVersion, const V&) -{ - unsigned int nSize = GetSizeOfCompactSize(v.size()); - for (typename std::vector::const_iterator vi = v.begin(); vi != v.end(); ++vi) - nSize += GetSerializeSize((*vi), nType, nVersion); - return nSize; -} - -template -inline unsigned int GetSerializeSize(const std::vector& v, int nType, int nVersion) -{ - return GetSerializeSize_impl(v, nType, nVersion, T()); -} - - template -void Serialize_impl(Stream& os, const std::vector& v, int nType, int nVersion, const unsigned char&) +void Serialize_impl(Stream& os, const std::vector& v, const unsigned char&) { WriteCompactSize(os, v.size()); if (!v.empty()) @@ -788,22 +687,22 @@ void Serialize_impl(Stream& os, const std::vector& v, int nType, int nVers } template -void Serialize_impl(Stream& os, const std::vector& v, int nType, int nVersion, const V&) +void Serialize_impl(Stream& os, const std::vector& v, const V&) { WriteCompactSize(os, v.size()); for (typename std::vector::const_iterator vi = v.begin(); vi != v.end(); ++vi) - ::Serialize(os, (*vi), nType, nVersion); + ::Serialize(os, (*vi)); } template -inline void Serialize(Stream& os, const std::vector& v, int nType, int nVersion) +inline void Serialize(Stream& os, const std::vector& v) { - Serialize_impl(os, v, nType, nVersion, T()); + Serialize_impl(os, v, T()); } template -void Unserialize_impl(Stream& is, std::vector& v, int nType, int nVersion, const unsigned char&) +void Unserialize_impl(Stream& is, std::vector& v, const unsigned char&) { // Limit size per read so bogus size value won't cause out of memory v.clear(); @@ -818,7 +717,7 @@ void Unserialize_impl(Stream& is, std::vector& v, int nType, int nVersion, } template -void Unserialize_impl(Stream& is, std::vector& v, int nType, int nVersion, const V&) +void Unserialize_impl(Stream& is, std::vector& v, const V&) { v.clear(); unsigned int nSize = ReadCompactSize(is); @@ -830,14 +729,14 @@ void Unserialize_impl(Stream& is, std::vector& v, int nType, int nVersion, nMid = nSize; v.resize(nMid); for (; i < nMid; i++) - Unserialize(is, v[i], nType, nVersion); + Unserialize(is, v[i]); } } template -inline void Unserialize(Stream& is, std::vector& v, int nType, int nVersion) +inline void Unserialize(Stream& is, std::vector& v) { - Unserialize_impl(is, v, nType, nVersion, T()); + Unserialize_impl(is, v, T()); } @@ -845,56 +744,41 @@ inline void Unserialize(Stream& is, std::vector& v, int nType, int nVersio /** * pair */ -template -unsigned int GetSerializeSize(const std::pair& item, int nType, int nVersion) -{ - return GetSerializeSize(item.first, nType, nVersion) + GetSerializeSize(item.second, nType, nVersion); -} - template -void Serialize(Stream& os, const std::pair& item, int nType, int nVersion) +void Serialize(Stream& os, const std::pair& item) { - Serialize(os, item.first, nType, nVersion); - Serialize(os, item.second, nType, nVersion); + Serialize(os, item.first); + Serialize(os, item.second); } template -void Unserialize(Stream& is, std::pair& item, int nType, int nVersion) +void Unserialize(Stream& is, std::pair& item) { - Unserialize(is, item.first, nType, nVersion); - Unserialize(is, item.second, nType, nVersion); + Unserialize(is, item.first); + Unserialize(is, item.second); } /** * map */ -template -unsigned int GetSerializeSize(const std::map& m, int nType, int nVersion) -{ - unsigned int nSize = GetSizeOfCompactSize(m.size()); - for (typename std::map::const_iterator mi = m.begin(); mi != m.end(); ++mi) - nSize += GetSerializeSize((*mi), nType, nVersion); - return nSize; -} - template -void Serialize(Stream& os, const std::map& m, int nType, int nVersion) +void Serialize(Stream& os, const std::map& m) { WriteCompactSize(os, m.size()); for (typename std::map::const_iterator mi = m.begin(); mi != m.end(); ++mi) - Serialize(os, (*mi), nType, nVersion); + Serialize(os, (*mi)); } template -void Unserialize(Stream& is, std::map& m, int nType, int nVersion) +void Unserialize(Stream& is, std::map& m) { m.clear(); unsigned int nSize = ReadCompactSize(is); typename std::map::iterator mi = m.begin(); for (unsigned int i = 0; i < nSize; i++) { std::pair item; - Unserialize(is, item, nType, nVersion); + Unserialize(is, item); mi = m.insert(mi, item); } } @@ -903,32 +787,23 @@ void Unserialize(Stream& is, std::map& m, int nType, int nVersion /** * set */ -template -unsigned int GetSerializeSize(const std::set& m, int nType, int nVersion) -{ - unsigned int nSize = GetSizeOfCompactSize(m.size()); - for (typename std::set::const_iterator it = m.begin(); it != m.end(); ++it) - nSize += GetSerializeSize((*it), nType, nVersion); - return nSize; -} - template -void Serialize(Stream& os, const std::set& m, int nType, int nVersion) +void Serialize(Stream& os, const std::set& m) { WriteCompactSize(os, m.size()); for (typename std::set::const_iterator it = m.begin(); it != m.end(); ++it) - Serialize(os, (*it), nType, nVersion); + Serialize(os, (*it)); } template -void Unserialize(Stream& is, std::set& m, int nType, int nVersion) +void Unserialize(Stream& is, std::set& m) { m.clear(); unsigned int nSize = ReadCompactSize(is); typename std::set::iterator it = m.begin(); for (unsigned int i = 0; i < nSize; i++) { K key; - Unserialize(is, key, nType, nVersion); + Unserialize(is, key); it = m.insert(it, key); } } @@ -938,40 +813,51 @@ void Unserialize(Stream& is, std::set& m, int nType, int nVersion) * Support for ADD_SERIALIZE_METHODS and READWRITE macro */ struct CSerActionSerialize { - bool ForRead() const { return false; } + constexpr bool ForRead() const { return false; } }; struct CSerActionUnserialize { - bool ForRead() const { return true; } + constexpr bool ForRead() const { return true; } }; template -inline void SerReadWrite(Stream& s, const T& obj, int nType, int nVersion, CSerActionSerialize ser_action) +inline void SerReadWrite(Stream& s, const T& obj, CSerActionSerialize ser_action) { - ::Serialize(s, obj, nType, nVersion); + ::Serialize(s, obj); } template -inline void SerReadWrite(Stream& s, T& obj, int nType, int nVersion, CSerActionUnserialize ser_action) +inline void SerReadWrite(Stream& s, T& obj, CSerActionUnserialize ser_action) { - ::Unserialize(s, obj, nType, nVersion); + ::Unserialize(s, obj); } + +/* ::GetSerializeSize implementations + * + * Computing the serialized size of objects is done through a special stream + * object of type CSizeComputer, which only records the number of bytes written + * to it. + * + * If your Serialize or SerializationOp method has non-trivial overhead for + * serialization, it may be worthwhile to implement a specialized version for + * CSizeComputer, which uses the s.seek() method to record bytes that would + * be written instead. + */ class CSizeComputer { protected: size_t nSize; -public: - int nType; - int nVersion; + const int nType; + const int nVersion; +public: CSizeComputer(int nTypeIn, int nVersionIn) : nSize(0), nType(nTypeIn), nVersion(nVersionIn) {} - CSizeComputer& write(const char* psz, size_t nSize) + void write(const char* psz, size_t _nSize) { - this->nSize += nSize; - return *this; + this->nSize += _nSize; } /** Pretend _nSize bytes are written, without specifying them. */ @@ -983,7 +869,7 @@ class CSizeComputer template CSizeComputer& operator<<(const T& obj) { - ::Serialize(*this, obj, nType, nVersion); + ::Serialize(*this, obj); return (*this); } @@ -991,6 +877,32 @@ class CSizeComputer { return nSize; } + + int GetVersion() const { return nVersion; } + int GetType() const { return nType; } }; +template +inline void WriteVarInt(CSizeComputer &s, I n) +{ + s.seek(GetSizeOfVarInt(n)); +} + +inline void WriteCompactSize(CSizeComputer &s, uint64_t nSize) +{ + s.seek(GetSizeOfCompactSize(nSize)); +} + +template +size_t GetSerializeSize(const T& t, int nType, int nVersion = 0) +{ + return (CSizeComputer(nType, nVersion) << t).size(); +} + +template +size_t GetSerializeSize(const S& s, const T& t) +{ + return (CSizeComputer(s.GetType(), s.GetVersion()) << t).size(); +} + #endif // AEZORA_SERIALIZE_H diff --git a/src/spork.h b/src/spork.h index cd0f5e535..4cee6d7ed 100644 --- a/src/spork.h +++ b/src/spork.h @@ -68,7 +68,7 @@ class CSporkMessage : public CSignedMessage ADD_SERIALIZE_METHODS; template - inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) + inline void SerializationOp(Stream& s, Operation ser_action) { READWRITE(nSporkID); READWRITE(nValue); @@ -99,7 +99,7 @@ class CSporkManager ADD_SERIALIZE_METHODS; template - inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) + inline void SerializationOp(Stream& s, Operation ser_action) { READWRITE(mapSporksActive); // we don't serialize private key to prevent its leakage diff --git a/src/sporkdb.cpp b/src/sporkdb.cpp index e7fc1fa79..2150db0cc 100644 --- a/src/sporkdb.cpp +++ b/src/sporkdb.cpp @@ -5,7 +5,7 @@ #include "sporkdb.h" #include "spork.h" -CSporkDB::CSporkDB(size_t nCacheSize, bool fMemory, bool fWipe) : CLevelDBWrapper(GetDataDir() / "sporks", nCacheSize, fMemory, fWipe) {} +CSporkDB::CSporkDB(size_t nCacheSize, bool fMemory, bool fWipe) : CDBWrapper(GetDataDir() / "sporks", nCacheSize, fMemory, fWipe) {} bool CSporkDB::WriteSpork(const SporkId nSporkId, const CSporkMessage& spork) { diff --git a/src/sporkdb.h b/src/sporkdb.h index 493013307..68a2d2178 100644 --- a/src/sporkdb.h +++ b/src/sporkdb.h @@ -6,10 +6,10 @@ #define AEZORA_CSPORKDB_H #include -#include "leveldbwrapper.h" +#include "dbwrapper.h" #include "spork.h" -class CSporkDB : public CLevelDBWrapper +class CSporkDB : public CDBWrapper { public: CSporkDB(size_t nCacheSize, bool fMemory = false, bool fWipe = false); diff --git a/src/streams.h b/src/streams.h index e0cb78dc0..ebb9b9455 100644 --- a/src/streams.h +++ b/src/streams.h @@ -35,10 +35,10 @@ class CDataStream vector_type vch; unsigned int nReadPos; -public: int nType; int nVersion; +public: typedef vector_type::allocator_type allocator_type; typedef vector_type::size_type size_type; typedef vector_type::difference_type difference_type; @@ -200,18 +200,16 @@ class CDataStream // // Stream subset // - bool eof() const { return size() == 0; } - CDataStream* rdbuf() { return this; } - int in_avail() { return size(); } + bool eof() const { return size() == 0; } + CDataStream* rdbuf() { return this; } + int in_avail() { return size(); } - void SetType(int n) { nType = n; } - int GetType() { return nType; } - void SetVersion(int n) { nVersion = n; } - int GetVersion() { return nVersion; } - void ReadVersion() { *this >> nVersion; } - void WriteVersion() { *this << nVersion; } + void SetType(int n) { nType = n; } + int GetType() const { return nType; } + void SetVersion(int n) { nVersion = n; } + int GetVersion() const { return nVersion; } - CDataStream& read(char* pch, size_t nSize) + void read(char* pch, size_t nSize) { // Read from the beginning of the buffer unsigned int nReadPosNext = nReadPos + nSize; @@ -222,11 +220,10 @@ class CDataStream memcpy(pch, &vch[nReadPos], nSize); nReadPos = 0; vch.clear(); - return (*this); + return; } memcpy(pch, &vch[nReadPos], nSize); nReadPos = nReadPosNext; - return (*this); } CDataStream& movePos(size_t nSize){ @@ -234,7 +231,7 @@ class CDataStream return (*this); } - CDataStream& ignore(int nSize) + void ignore(int nSize) { // Ignore from the beginning of the buffer if (nSize < 0) { @@ -246,39 +243,30 @@ class CDataStream throw std::ios_base::failure("CDataStream::ignore() : end of data"); nReadPos = 0; vch.clear(); - return (*this); + return; } nReadPos = nReadPosNext; - return (*this); } - CDataStream& write(const char* pch, size_t nSize) + void write(const char* pch, size_t nSize) { // Write to the end of the buffer vch.insert(vch.end(), pch, pch + nSize); - return (*this); } template - void Serialize(Stream& s, int nType, int nVersion) const + void Serialize(Stream& s) const { // Special case: stream << stream concatenates like stream += stream if (!vch.empty()) s.write((char*)&vch[0], vch.size() * sizeof(vch[0])); } - template - unsigned int GetSerializeSize(const T& obj) - { - // Tells the size of the object if serialized to this stream - return ::GetSerializeSize(obj, nType, nVersion); - } - template CDataStream& operator<<(const T& obj) { // Serialize to this stream - ::Serialize(*this, obj, nType, nVersion); + ::Serialize(*this, obj); return (*this); } @@ -286,7 +274,7 @@ class CDataStream CDataStream& operator>>(T& obj) { // Unserialize from this stream - ::Unserialize(*this, obj, nType, nVersion); + ::Unserialize(*this, obj); return (*this); } @@ -311,17 +299,15 @@ class CAutoFile CAutoFile(const CAutoFile&); CAutoFile& operator=(const CAutoFile&); - int nType; - int nVersion; + const int nType; + const int nVersion; FILE* file; public: - CAutoFile(FILE* filenew, int nTypeIn, int nVersionIn) + CAutoFile(FILE* filenew, int nTypeIn, int nVersionIn) : nType(nTypeIn), nVersion(nVersionIn) { file = filenew; - nType = nTypeIn; - nVersion = nVersionIn; } ~CAutoFile() @@ -361,23 +347,18 @@ class CAutoFile // // Stream subset // - void SetType(int n) { nType = n; } - int GetType() { return nType; } - void SetVersion(int n) { nVersion = n; } - int GetVersion() { return nVersion; } - void ReadVersion() { *this >> nVersion; } - void WriteVersion() { *this << nVersion; } + int GetType() const { return nType; } + int GetVersion() const { return nVersion; } - CAutoFile& read(char* pch, size_t nSize) + void read(char* pch, size_t nSize) { if (!file) throw std::ios_base::failure("CAutoFile::read : file handle is NULL"); if (fread(pch, 1, nSize, file) != nSize) throw std::ios_base::failure(feof(file) ? "CAutoFile::read : end of file" : "CAutoFile::read : fread failed"); - return (*this); } - CAutoFile& ignore(size_t nSize) + void ignore(size_t nSize) { if (!file) throw std::ios_base::failure("CAutoFile::ignore: file handle is NULL"); @@ -388,24 +369,15 @@ class CAutoFile throw std::ios_base::failure(feof(file) ? "CAutoFile::ignore: end of file" : "CAutoFile::read: fread failed"); nSize -= nNow; } - return (*this); } - CAutoFile& write(const char* pch, size_t nSize) + void write(const char* pch, size_t nSize) { if (!file) throw std::ios_base::failure("CAutoFile::write : file handle is NULL"); if (fwrite(pch, 1, nSize, file) != nSize) throw std::ios_base::failure("CAutoFile::write : write failed"); - return (*this); - } - - template - unsigned int GetSerializeSize(const T& obj) - { - // Tells the size of the object if serialized to this stream - return ::GetSerializeSize(obj, nType, nVersion); } template @@ -414,7 +386,7 @@ class CAutoFile // Serialize to this stream if (!file) throw std::ios_base::failure("CAutoFile::operator<< : file handle is NULL"); - ::Serialize(*this, obj, nType, nVersion); + ::Serialize(*this, obj); return (*this); } @@ -424,7 +396,7 @@ class CAutoFile // Unserialize from this stream if (!file) throw std::ios_base::failure("CAutoFile::operator>> : file handle is NULL"); - ::Unserialize(*this, obj, nType, nVersion); + ::Unserialize(*this, obj); return (*this); } }; @@ -442,8 +414,8 @@ class CBufferedFile CBufferedFile(const CBufferedFile&); CBufferedFile& operator=(const CBufferedFile&); - int nType; - int nVersion; + const int nType; + const int nVersion; FILE* src; // source file uint64_t nSrcPos; // how many bytes have been read from source @@ -473,11 +445,10 @@ class CBufferedFile } public: - CBufferedFile(FILE* fileIn, uint64_t nBufSize, uint64_t nRewindIn, int nTypeIn, int nVersionIn) : nSrcPos(0), nReadPos(0), nReadLimit((uint64_t)(-1)), nRewind(nRewindIn), vchBuf(nBufSize, 0) + CBufferedFile(FILE* fileIn, uint64_t nBufSize, uint64_t nRewindIn, int nTypeIn, int nVersionIn) : + nType(nTypeIn), nVersion(nVersionIn), nSrcPos(0), nReadPos(0), nReadLimit((uint64_t)(-1)), nRewind(nRewindIn), vchBuf(nBufSize, 0) { src = fileIn; - nType = nTypeIn; - nVersion = nVersionIn; } ~CBufferedFile() @@ -500,7 +471,7 @@ class CBufferedFile } // read a number of bytes - CBufferedFile& read(char* pch, size_t nSize) + void read(char* pch, size_t nSize) { if (nSize + nReadPos > nReadLimit) throw std::ios_base::failure("Read attempted past buffer limit"); @@ -520,7 +491,6 @@ class CBufferedFile pch += nNow; nSize -= nNow; } - return (*this); } // return the current reading position @@ -571,7 +541,7 @@ class CBufferedFile CBufferedFile& operator>>(T& obj) { // Unserialize from this stream - ::Unserialize(*this, obj, nType, nVersion); + ::Unserialize(*this, obj); return (*this); } diff --git a/src/swifttx.h b/src/swifttx.h index 6755305ed..12439cf36 100644 --- a/src/swifttx.h +++ b/src/swifttx.h @@ -88,7 +88,7 @@ class CConsensusVote : public CSignedMessage ADD_SERIALIZE_METHODS; template - inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) + inline void SerializationOp(Stream& s, Operation ser_action) { READWRITE(txHash); READWRITE(vinMasternode); diff --git a/src/test/benchmark_zerocoin.cpp b/src/test/benchmark_zerocoin.cpp deleted file mode 100644 index 641e962dd..000000000 --- a/src/test/benchmark_zerocoin.cpp +++ /dev/null @@ -1,414 +0,0 @@ -/** - * @file Benchmark.cpp - * - * @brief Benchmarking tests for Zerocoin. - * - * @author Ian Miers, Christina Garman and Matthew Green - * @date June 2013 - * - * @copyright Copyright 2013 Ian Miers, Christina Garman and Matthew Green - * @license This project is released under the MIT license. - **/ -// Copyright (c) 2017-2019 The AEZORA developers - -#include -#include -#include -#include -// #include -#include -#include -#include -#include "streams.h" -#include "libzerocoin/ParamGeneration.h" -#include "libzerocoin/Denominations.h" -#include "libzerocoin/Coin.h" -#include "libzerocoin/CoinSpend.h" -#include "libzerocoin/Accumulator.h" -#include "test_aezora.h" - - -#define COLOR_STR_GREEN "\033[32m" -#define COLOR_STR_NORMAL "\033[0m" -#define COLOR_STR_RED "\033[31m" - -#define TESTS_COINS_TO_ACCUMULATE 50 - -// Global test counters -uint32_t ggNumTests = 0; -uint32_t ggSuccessfulTests = 0; - -// Global coin array -libzerocoin::PrivateCoin *ggCoins[TESTS_COINS_TO_ACCUMULATE]; - -// Global params -libzerocoin::ZerocoinParams *gg_Params; - -////////// -// Utility routines -////////// - -class Timer -{ - timeval timer[2]; - -public: - - timeval start() - { - gettimeofday(&this->timer[0], NULL); - return this->timer[0]; - } - - timeval stop() - { - gettimeofday(&this->timer[1], NULL); - return this->timer[1]; - } - - int duration() const - { - int secs(this->timer[1].tv_sec - this->timer[0].tv_sec); - int usecs(this->timer[1].tv_usec - this->timer[0].tv_usec); - - if(usecs < 0) - { - --secs; - usecs += 1000000; - } - - return static_cast(secs * 1000 + usecs / 1000.0 + 0.5); - } -}; - -// Global timer -Timer timer; - -void -gLogTestResult(std::string testName, bool (*testPtr)()) -{ - std::string colorGreen(COLOR_STR_GREEN); - std::string colorNormal(COLOR_STR_NORMAL); - std::string colorRed(COLOR_STR_RED); - - std::cout << "Testing if " << testName << "..." << std::endl; - - bool testResult = testPtr(); - - if (testResult == true) { - std::cout << "\t" << colorGreen << "[PASS]" << colorNormal << std::endl; - ggSuccessfulTests++; - } else { - std::cout << colorRed << "\t[FAIL]" << colorNormal << std::endl; - } - - ggNumTests++; -} - -CBigNum -gGetTestModulus() -{ - static CBigNum testModulus(0); - - // TODO: should use a hard-coded RSA modulus for testing - if (!testModulus) { - CBigNum p, q; - p = CBigNum::generatePrime(1024, false); - q = CBigNum::generatePrime(1024, false); - testModulus = p * q; - } - - return testModulus; -} - -////////// -// Test routines -////////// - - -bool -Testb_GenRSAModulus() -{ - CBigNum result = gGetTestModulus(); - - if (!result) { - return false; - } - else { - return true; - } -} - -bool -Testb_CalcParamSizes() -{ - bool result = true; -#if 0 - - uint32_t pLen, qLen; - - try { - calculateGroupParamLengths(4000, 80, &pLen, &qLen); - if (pLen < 1024 || qLen < 256) { - result = false; - } - calculateGroupParamLengths(4000, 96, &pLen, &qLen); - if (pLen < 2048 || qLen < 256) { - result = false; - } - calculateGroupParamLengths(4000, 112, &pLen, &qLen); - if (pLen < 3072 || qLen < 320) { - result = false; - } - calculateGroupParamLengths(4000, 120, &pLen, &qLen); - if (pLen < 3072 || qLen < 320) { - result = false; - } - calculateGroupParamLengths(4000, 128, &pLen, &qLen); - if (pLen < 3072 || qLen < 320) { - result = false; - } - } catch (const exception &e) { - result = false; - } -#endif - - return result; -} - -bool -Testb_GenerateGroupParams() -{ - uint32_t pLen = 1024, qLen = 256, count; - libzerocoin::IntegerGroupParams group; - - for (count = 0; count < 1; count++) { - - try { - group = libzerocoin::deriveIntegerGroupParams(libzerocoin::calculateSeed(gGetTestModulus(), "test", ZEROCOIN_DEFAULT_SECURITYLEVEL, "TEST GROUP"), pLen, qLen); - } catch (const std::runtime_error& e) { - std::cout << "Caught exception " << e.what() << std::endl; - return false; - } - - // Now perform some simple tests on the resulting parameters - if ((uint32_t)group.groupOrder.bitSize() < qLen || (uint32_t)group.modulus.bitSize() < pLen) { - return false; - } - - CBigNum c = group.g.pow_mod(group.groupOrder, group.modulus); - //cout << "g^q mod p = " << c << std::endl; - if (!(c.isOne())) return false; - - // Try at multiple parameter sizes - pLen = pLen * 1.5; - qLen = qLen * 1.5; - } - - return true; -} - -bool -Testb_ParamGen() -{ - bool result = true; - - try { - timer.start(); - // Instantiating testParams runs the parameter generation code - libzerocoin::ZerocoinParams testParams(gGetTestModulus(),ZEROCOIN_DEFAULT_SECURITYLEVEL); - timer.stop(); - - std::cout << "\tPARAMGEN ELAPSED TIME: " << timer.duration() << " ms\t" << timer.duration()*0.001 << " s" << std::endl; - } catch (const std::runtime_error& e) { - std::cout << e.what() << std::endl; - result = false; - } - - return result; -} - -bool -Testb_Accumulator() -{ - // This test assumes a list of coins were generated during - // the Testb_MintCoin() test. - if (ggCoins[0] == NULL) { - return false; - } - try { - // Accumulate the coin list from first to last into one accumulator - libzerocoin::Accumulator accOne(&gg_Params->accumulatorParams,libzerocoin::CoinDenomination::ZQ_ONE); - libzerocoin::Accumulator accTwo(&gg_Params->accumulatorParams,libzerocoin::CoinDenomination::ZQ_ONE); - libzerocoin::Accumulator accThree(&gg_Params->accumulatorParams,libzerocoin::CoinDenomination::ZQ_ONE); - libzerocoin::Accumulator accFour(&gg_Params->accumulatorParams,libzerocoin::CoinDenomination::ZQ_ONE); - libzerocoin::AccumulatorWitness wThree(gg_Params, accThree, ggCoins[0]->getPublicCoin()); - - for (uint32_t i = 0; i < TESTS_COINS_TO_ACCUMULATE; i++) { - accOne += ggCoins[i]->getPublicCoin(); - accTwo += ggCoins[TESTS_COINS_TO_ACCUMULATE - (i+1)]->getPublicCoin(); - accThree += ggCoins[i]->getPublicCoin(); - wThree += ggCoins[i]->getPublicCoin(); - if(i != 0) { - accFour += ggCoins[i]->getPublicCoin(); - } - } - - // Compare the accumulated results - if (accOne.getValue() != accTwo.getValue() || accOne.getValue() != accThree.getValue()) { - std::cout << "Accumulators don't match" << std::endl; - return false; - } - - if(accFour.getValue() != wThree.getValue()) { - std::cout << "Witness math not working," << std::endl; - return false; - } - - // Verify that the witness is correct - if (!wThree.VerifyWitness(accThree, ggCoins[0]->getPublicCoin()) ) { - std::cout << "Witness not valid" << std::endl; - return false; - } - - } catch (const std::runtime_error& e) { - std::cout << e.what() << std::endl; - return false; - } - - return true; -} - -bool -Testb_MintCoin() -{ - try { - // Generate a list of coins - timer.start(); - for (uint32_t i = 0; i < TESTS_COINS_TO_ACCUMULATE; i++) { - ggCoins[i] = new libzerocoin::PrivateCoin(gg_Params, libzerocoin::CoinDenomination::ZQ_ONE); - } - timer.stop(); - } catch (const std::exception& e) { - return false; - } - - std::cout << "\tMINT ELAPSED TIME:\n\t\tTotal: " << timer.duration() << " ms\t" << timer.duration()*0.001 << " s\n\t\tPer Coin: " << timer.duration()/TESTS_COINS_TO_ACCUMULATE << " ms\t" << (timer.duration()/TESTS_COINS_TO_ACCUMULATE)*0.001 << " s" << std::endl; - - return true; -} - -bool -Testb_MintAndSpend() -{ - try { - // This test assumes a list of coins were generated in Testb_MintCoin() - if (ggCoins[0] == NULL) - { - // No coins: mint some. - Testb_MintCoin(); - if (ggCoins[0] == NULL) { - return false; - } - } - - // Accumulate the list of generated coins into a fresh accumulator. - // The first one gets marked as accumulated for a witness, the - // others just get accumulated normally. - libzerocoin::Accumulator acc(&gg_Params->accumulatorParams, libzerocoin::CoinDenomination::ZQ_ONE); - libzerocoin::AccumulatorWitness wAcc(gg_Params, acc, ggCoins[0]->getPublicCoin()); - - timer.start(); - for (uint32_t i = 0; i < TESTS_COINS_TO_ACCUMULATE; i++) { - acc += ggCoins[i]->getPublicCoin(); - } - timer.stop(); - - std::cout << "\tACCUMULATOR ELAPSED TIME:\n\t\tTotal: " << timer.duration() << " ms\t" << timer.duration()*0.001 << " s\n\t\tPer Element: " << timer.duration()/TESTS_COINS_TO_ACCUMULATE << " ms\t" << (timer.duration()/TESTS_COINS_TO_ACCUMULATE)*0.001 << " s" << std::endl; - - timer.start(); - for (uint32_t i = 0; i < TESTS_COINS_TO_ACCUMULATE; i++) { - wAcc +=ggCoins[i]->getPublicCoin(); - } - timer.stop(); - - std::cout << "\tWITNESS ELAPSED TIME: \n\t\tTotal: " << timer.duration() << " ms\t" << timer.duration()*0.001 << " s\n\t\tPer Element: " << timer.duration()/TESTS_COINS_TO_ACCUMULATE << " ms\t" << (timer.duration()/TESTS_COINS_TO_ACCUMULATE)*0.001 << " s" << std::endl; - - // Now spend the coin - timer.start(); - libzerocoin::CoinSpend spend(gg_Params, gg_Params, *(ggCoins[0]), acc, 0, wAcc, 0, libzerocoin::SpendType::SPEND); //(0) presstab - timer.stop(); - - std::cout << "\tSPEND ELAPSED TIME: " << timer.duration() << " ms\t" << timer.duration()*0.001 << " s" << std::endl; - - // Serialize the proof and deserialize into newSpend - CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); - - timer.start(); - ss << spend; - timer.stop(); - - libzerocoin::CoinSpend newSpend(gg_Params, gg_Params, ss); - - std::cout << "\tSERIALIZE ELAPSED TIME: " << timer.duration() << " ms\t" << timer.duration()*0.001 << " s" << std::endl; - - // Finally, see if we can verify the deserialized proof (return our result) - timer.start(); - bool ret = newSpend.Verify(acc); - timer.stop(); - - std::cout << "\tSPEND VERIFY ELAPSED TIME: " << timer.duration() << " ms\t" << timer.duration()*0.001 << " s" << std::endl; - - return ret; - } catch (const std::runtime_error& e) { - std::cout << e.what() << std::endl; - return false; - } - - return false; -} - -void -Testb_RunAllTests() -{ - // Make a new set of parameters from a random RSA modulus - gg_Params = new libzerocoin::ZerocoinParams(gGetTestModulus()); - - ggNumTests = ggSuccessfulTests = 0; - for (uint32_t i = 0; i < TESTS_COINS_TO_ACCUMULATE; i++) { - ggCoins[i] = NULL; - } - - // Run through all of the Zerocoin tests - gLogTestResult("an RSA modulus can be generated", Testb_GenRSAModulus); - gLogTestResult("parameter sizes are correct", Testb_CalcParamSizes); - gLogTestResult("group/field parameters can be generated", Testb_GenerateGroupParams); - gLogTestResult("parameter generation is correct", Testb_ParamGen); - gLogTestResult("coins can be minted", Testb_MintCoin); - gLogTestResult("the accumulator works", Testb_Accumulator); - gLogTestResult("a minted coin can be spent", Testb_MintAndSpend); - - // Summarize test results - if (ggSuccessfulTests < ggNumTests) { - std::cout << std::endl << "ERROR: SOME TESTS FAILED" << std::endl; - } - - // Clear any generated coins - for (uint32_t i = 0; i < TESTS_COINS_TO_ACCUMULATE; i++) { - delete ggCoins[i]; - } - - std::cout << ggSuccessfulTests << " out of " << ggNumTests << " tests passed." << std::endl << std::endl; - delete gg_Params; -} - -BOOST_FIXTURE_TEST_SUITE(benchmark_zerocoin, TestingSetup) - -BOOST_AUTO_TEST_CASE(benchmark_test) -{ - std::cout << "libzerocoin v" << ZEROCOIN_VERSION_STRING << " benchmark utility." << std::endl << std::endl; - - Testb_RunAllTests(); -} -BOOST_AUTO_TEST_SUITE_END() - diff --git a/src/test/dbwrapper_tests.cpp b/src/test/dbwrapper_tests.cpp new file mode 100644 index 000000000..1f0fadb0d --- /dev/null +++ b/src/test/dbwrapper_tests.cpp @@ -0,0 +1,117 @@ +// Copyright (c) 2012-2013 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 "dbwrapper.h" +#include "uint256.h" +#include "random.h" +#include "test/test_aezora.h" + +#include // for 'operator+=()' +#include +#include + + +// Test if a string consists entirely of null characters +bool is_null_key(const std::vector& key) { + bool isnull = true; + + for (unsigned int i = 0; i < key.size(); i++) + isnull &= (key[i] == '\x00'); + + return isnull; +} + +BOOST_FIXTURE_TEST_SUITE(dbwrapper_tests, BasicTestingSetup) + +BOOST_AUTO_TEST_CASE(dbwrapper) +{ + { + boost::filesystem::path ph = boost::filesystem::temp_directory_path() / boost::filesystem::unique_path(); + CDBWrapper dbw(ph, (1 << 20), true, false); + char key = 'k'; + uint256 in = GetRandHash(); + uint256 res; + + BOOST_CHECK(dbw.Write(key, in)); + BOOST_CHECK(dbw.Read(key, res)); + BOOST_CHECK_EQUAL(res.ToString(), in.ToString()); + } +} + +// Test batch operations +BOOST_AUTO_TEST_CASE(dbwrapper_batch) +{ + { + boost::filesystem::path ph = boost::filesystem::temp_directory_path() / boost::filesystem::unique_path(); + CDBWrapper dbw(ph, (1 << 20), true, false); + + char key = 'i'; + uint256 in = GetRandHash(); + char key2 = 'j'; + uint256 in2 = GetRandHash(); + char key3 = 'k'; + uint256 in3 = GetRandHash(); + + uint256 res; + CDBBatch batch; + + batch.Write(key, in); + batch.Write(key2, in2); + batch.Write(key3, in3); + + // Remove key3 before it's even been written + batch.Erase(key3); + + dbw.WriteBatch(batch); + + BOOST_CHECK(dbw.Read(key, res)); + BOOST_CHECK_EQUAL(res.ToString(), in.ToString()); + BOOST_CHECK(dbw.Read(key2, res)); + BOOST_CHECK_EQUAL(res.ToString(), in2.ToString()); + + // key3 never should've been written + BOOST_CHECK(dbw.Read(key3, res) == false); + } +} + +BOOST_AUTO_TEST_CASE(dbwrapper_iterator) +{ + { + boost::filesystem::path ph = boost::filesystem::temp_directory_path() / boost::filesystem::unique_path(); + CDBWrapper dbw(ph, (1 << 20), true, false); + + // The two keys are intentionally chosen for ordering + char key = 'j'; + uint256 in = GetRandHash(); + BOOST_CHECK(dbw.Write(key, in)); + char key2 = 'k'; + uint256 in2 = GetRandHash(); + BOOST_CHECK(dbw.Write(key2, in2)); + + boost::scoped_ptr it(const_cast(&dbw)->NewIterator()); + + // Be sure to seek past any earlier key (if it exists) + it->Seek(key); + + char key_res; + uint256 val_res; + + it->GetKey(key_res); + it->GetValue(val_res); + BOOST_CHECK_EQUAL(key_res, key); + BOOST_CHECK_EQUAL(val_res.ToString(), in.ToString()); + + it->Next(); + + it->GetKey(key_res); + it->GetValue(val_res); + BOOST_CHECK_EQUAL(key_res, key2); + BOOST_CHECK_EQUAL(val_res.ToString(), in2.ToString()); + + it->Next(); + BOOST_CHECK_EQUAL(it->Valid(), false); + } +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/libzerocoin_tests.cpp b/src/test/libzerocoin_tests.cpp deleted file mode 100644 index 12bd8cbe8..000000000 --- a/src/test/libzerocoin_tests.cpp +++ /dev/null @@ -1,493 +0,0 @@ -/** -* @file Tests.cpp -* -* @brief Test routines for Zerocoin. -* -* @author Ian Miers, Christina Garman and Matthew Green -* @date June 2013 -* -* @copyright Copyright 2013 Ian Miers, Christina Garman and Matthew Green -* @license This project is released under the MIT license. -**/ -// Copyright (c) 2017-2019 The AEZORA developers - -#include -#include -#include -#include -#include -// #include -#include -#include "streams.h" -#include "libzerocoin/ParamGeneration.h" -#include "libzerocoin/Denominations.h" -#include "libzerocoin/Coin.h" -#include "libzerocoin/CoinSpend.h" -#include "libzerocoin/Accumulator.h" -#include "test_aezora.h" - - -#define COLOR_STR_GREEN "\033[32m" -#define COLOR_STR_NORMAL "\033[0m" -#define COLOR_STR_RED "\033[31m" - -#define TESTS_COINS_TO_ACCUMULATE 10 -#define NON_PRIME_TESTS 100 - -// Global test counters -uint32_t gNumTests = 0; -uint32_t gSuccessfulTests = 0; - -// Proof size -uint32_t gProofSize = 0; -uint32_t gCoinSize = 0; -uint32_t gSerialNumberSize = 0; - -// Global coin array -libzerocoin::PrivateCoin *gCoins[TESTS_COINS_TO_ACCUMULATE]; - -// Global params -libzerocoin::ZerocoinParams *g_Params; - -////////// -// Utility routines -////////// - -void -LogTestResult(std::string testName, bool (*testPtr)()) -{ - std::string colorGreen(COLOR_STR_GREEN); - std::string colorNormal(COLOR_STR_NORMAL); - std::string colorRed(COLOR_STR_RED); - - std::cout << "Testing if " << testName << "..." << std::endl; - - bool testResult = testPtr(); - - if (testResult == true) { - std::cout << "\t" << colorGreen << "[PASS]" << colorNormal << std::endl; - gSuccessfulTests++; - } else { - std::cout << colorRed << "\t[FAIL]" << colorNormal << std::endl; - } - - gNumTests++; -} - -CBigNum -GetTestModulus() -{ - static CBigNum testModulus(0); - - // TODO: should use a hard-coded RSA modulus for testing - if (!testModulus) { - CBigNum p, q; - - // Note: we are NOT using safe primes for testing because - // they take too long to generate. Don't do this in real - // usage. See the paramgen utility for better code. - p = CBigNum::generatePrime(1024, false); - q = CBigNum::generatePrime(1024, false); - testModulus = p * q; - } - - return testModulus; -} - -////////// -// Test routines -////////// - -bool -Test_GenRSAModulus() -{ - CBigNum result = GetTestModulus(); - - if (!result) { - return false; - } - else { - return true; - } -} - -bool -Test_CalcParamSizes() -{ - bool result = true; -#if 0 - - uint32_t pLen, qLen; - - try { - calculateGroupParamLengths(4000, 80, &pLen, &qLen); - if (pLen < 1024 || qLen < 256) { - result = false; - } - calculateGroupParamLengths(4000, 96, &pLen, &qLen); - if (pLen < 2048 || qLen < 256) { - result = false; - } - calculateGroupParamLengths(4000, 112, &pLen, &qLen); - if (pLen < 3072 || qLen < 320) { - result = false; - } - calculateGroupParamLengths(4000, 120, &pLen, &qLen); - if (pLen < 3072 || qLen < 320) { - result = false; - } - calculateGroupParamLengths(4000, 128, &pLen, &qLen); - if (pLen < 3072 || qLen < 320) { - result = false; - } - } catch (const exception& e) { - result = false; - } -#endif - - return result; -} - -bool -Test_GenerateGroupParams() -{ - uint32_t pLen = 1024, qLen = 256, count; - libzerocoin::IntegerGroupParams group; - - for (count = 0; count < 1; count++) { - - try { - group = libzerocoin::deriveIntegerGroupParams(libzerocoin::calculateSeed(GetTestModulus(), "test", ZEROCOIN_DEFAULT_SECURITYLEVEL, "TEST GROUP"), pLen, qLen); - } catch (const std::runtime_error& e) { - std::cout << "Caught exception " << e.what() << std::endl; - return false; - } - - // Now perform some simple tests on the resulting parameters - if ((uint32_t)group.groupOrder.bitSize() < qLen || (uint32_t)group.modulus.bitSize() < pLen) { - return false; - } - - CBigNum c = group.g.pow_mod(group.groupOrder, group.modulus); - //cout << "g^q mod p = " << c << std::endl; - if (!(c.isOne())) return false; - - // Try at multiple parameter sizes - pLen = pLen * 1.5; - qLen = qLen * 1.5; - } - - return true; -} - -bool -Test_ParamGen() -{ - bool result = true; - - try { - // Instantiating testParams runs the parameter generation code - libzerocoin::ZerocoinParams testParams(GetTestModulus(),ZEROCOIN_DEFAULT_SECURITYLEVEL); - } catch (const std::runtime_error& e) { - std::cout << e.what() << std::endl; - result = false; - } - - return result; -} - -bool -Test_Accumulator() -{ - // This test assumes a list of coins were generated during - // the Test_MintCoin() test. - if (gCoins[0] == NULL) { - return false; - } - try { - // Accumulate the coin list from first to last into one accumulator - libzerocoin::Accumulator accOne(&g_Params->accumulatorParams, libzerocoin::CoinDenomination::ZQ_ONE); - libzerocoin::Accumulator accTwo(&g_Params->accumulatorParams, libzerocoin::CoinDenomination::ZQ_ONE); - libzerocoin::Accumulator accThree(&g_Params->accumulatorParams, libzerocoin::CoinDenomination::ZQ_ONE); - libzerocoin::Accumulator accFour(&g_Params->accumulatorParams, libzerocoin::CoinDenomination::ZQ_ONE); - libzerocoin::AccumulatorWitness wThree(g_Params, accThree, gCoins[0]->getPublicCoin()); - - for (uint32_t i = 0; i < TESTS_COINS_TO_ACCUMULATE; i++) { - accOne += gCoins[i]->getPublicCoin(); - accTwo += gCoins[TESTS_COINS_TO_ACCUMULATE - (i+1)]->getPublicCoin(); - accThree += gCoins[i]->getPublicCoin(); - wThree += gCoins[i]->getPublicCoin(); - if(i != 0) { - accFour += gCoins[i]->getPublicCoin(); - } - } - - // Compare the accumulated results - if (accOne.getValue() != accTwo.getValue() || accOne.getValue() != accThree.getValue()) { - std::cout << "Accumulators don't match" << std::endl; - return false; - } - - if(accFour.getValue() != wThree.getValue()) { - std::cout << "Witness math not working," << std::endl; - return false; - } - - // Verify that the witness is correct - if (!wThree.VerifyWitness(accThree, gCoins[0]->getPublicCoin()) ) { - std::cout << "Witness not valid" << std::endl; - return false; - } - - // Serialization test: see if we can serialize the accumulator - CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); - ss << accOne; - - // Deserialize it into a new object - libzerocoin::Accumulator newAcc(g_Params, ss); - - // Compare the results - if (accOne.getValue() != newAcc.getValue()) { - return false; - } - - } catch (const std::runtime_error& e) { - return false; - } - - return true; -} - -bool -Test_EqualityPoK() -{ - // Run this test 10 times - for (uint32_t i = 0; i < 10; i++) { - try { - // Generate a random integer "val" - CBigNum val = CBigNum::randBignum(g_Params->coinCommitmentGroup.groupOrder); - - // Manufacture two commitments to "val", both - // under different sets of parameters - libzerocoin::Commitment one(&g_Params->accumulatorParams.accumulatorPoKCommitmentGroup, val); - - libzerocoin::Commitment two(&g_Params->serialNumberSoKCommitmentGroup, val); - - // Now generate a proof of knowledge that "one" and "two" are - // both commitments to the same value - libzerocoin::CommitmentProofOfKnowledge pok(&g_Params->accumulatorParams.accumulatorPoKCommitmentGroup, - &g_Params->serialNumberSoKCommitmentGroup, - one, two); - - // Serialize the proof into a stream - CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); - ss << pok; - - // Deserialize back into a PoK object - libzerocoin::CommitmentProofOfKnowledge newPok(&g_Params->accumulatorParams.accumulatorPoKCommitmentGroup, - &g_Params->serialNumberSoKCommitmentGroup, - ss); - - if (newPok.Verify(one.getCommitmentValue(), two.getCommitmentValue()) != true) { - return false; - } - - // Just for fun, deserialize the proof a second time - CDataStream ss2(SER_NETWORK, PROTOCOL_VERSION); - ss2 << pok; - - // This time tamper with it, then deserialize it back into a PoK - ss2[15] = 0; - libzerocoin::CommitmentProofOfKnowledge newPok2(&g_Params->accumulatorParams.accumulatorPoKCommitmentGroup, - &g_Params->serialNumberSoKCommitmentGroup, - ss2); - - // If the tampered proof verifies, that's a failure! - if (newPok2.Verify(one.getCommitmentValue(), two.getCommitmentValue()) == true) { - return false; - } - - } catch (const std::runtime_error& e) { - return false; - } - } - - return true; -} - -bool -Test_MintCoin() -{ - gCoinSize = 0; - - try { - // Generate a list of coins - for (uint32_t i = 0; i < TESTS_COINS_TO_ACCUMULATE; i++) { - gCoins[i] = new libzerocoin::PrivateCoin(g_Params,libzerocoin::CoinDenomination::ZQ_ONE); - - libzerocoin::PublicCoin pc = gCoins[i]->getPublicCoin(); - CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); - ss << pc; - gCoinSize += ss.size(); - } - - gCoinSize /= TESTS_COINS_TO_ACCUMULATE; - - } catch (const std::exception& e) { - return false; - } - - return true; -} - -bool Test_InvalidCoin() -{ - CBigNum coinValue; - - try { - // Pick a random non-prime CBigNum - for (uint32_t i = 0; i < NON_PRIME_TESTS; i++) { - coinValue = CBigNum::randBignum(g_Params->coinCommitmentGroup.modulus); - coinValue = coinValue * 2; - if (!coinValue.isPrime()) break; - } - - libzerocoin::PublicCoin pubCoin(g_Params); - if (pubCoin.validate()) { - // A blank coin should not be valid! - return false; - } - - libzerocoin::PublicCoin pubCoin2(g_Params, coinValue, libzerocoin::ZQ_ONE); - if (pubCoin2.validate()) { - // A non-prime coin should not be valid! - return false; - } - - libzerocoin::PublicCoin pubCoin3 = pubCoin2; - if (pubCoin2.validate()) { - // A copy of a non-prime coin should not be valid! - return false; - } - - // Serialize and deserialize the coin - CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); - ss << pubCoin; - libzerocoin::PublicCoin pubCoin4(g_Params, ss); - if (pubCoin4.validate()) { - // A deserialized copy of a non-prime coin should not be valid! - return false; - } - - } catch (const std::runtime_error& e) { - std::cout << "Caught exception: " << e.what() << std::endl; - return false; - } - - return true; -} - -bool -Test_MintAndSpend() -{ - try { - // This test assumes a list of coins were generated in Test_MintCoin() - if (gCoins[0] == NULL) - { - // No coins: mint some. - Test_MintCoin(); - if (gCoins[0] == NULL) { - return false; - } - } - - // Accumulate the list of generated coins into a fresh accumulator. - // The first one gets marked as accumulated for a witness, the - // others just get accumulated normally. - libzerocoin::Accumulator acc(&g_Params->accumulatorParams, libzerocoin::CoinDenomination::ZQ_ONE); - libzerocoin::AccumulatorWitness wAcc(g_Params, acc, gCoins[0]->getPublicCoin()); - - for (uint32_t i = 0; i < TESTS_COINS_TO_ACCUMULATE; i++) { - acc += gCoins[i]->getPublicCoin(); - wAcc +=gCoins[i]->getPublicCoin(); - } - - // Now spend the coin - //SpendMetaData m(1,1); - CDataStream cc(SER_NETWORK, PROTOCOL_VERSION); - cc << *gCoins[0]; - libzerocoin::PrivateCoin myCoin(g_Params,cc); - - libzerocoin::CoinSpend spend(g_Params, g_Params, myCoin, acc, 0, wAcc, 0, libzerocoin::SpendType::SPEND); - spend.Verify(acc); - - // Serialize the proof and deserialize into newSpend - CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); - ss << spend; - gProofSize = ss.size(); - libzerocoin::CoinSpend newSpend(g_Params, g_Params, ss); - - // See if we can verify the deserialized proof (return our result) - bool ret = newSpend.Verify(acc); - - // Extract the serial number - CBigNum serialNumber = newSpend.getCoinSerialNumber(); - gSerialNumberSize = ceil((double)serialNumber.bitSize() / 8.0); - - return ret; - } catch (const std::runtime_error& e) { - std::cout << e.what() << std::endl; - return false; - } - - return false; -} - -void -Test_RunAllTests() -{ - // Make a new set of parameters from a random RSA modulus - g_Params = new libzerocoin::ZerocoinParams(GetTestModulus()); - - gNumTests = gSuccessfulTests = gProofSize = 0; - for (uint32_t i = 0; i < TESTS_COINS_TO_ACCUMULATE; i++) { - gCoins[i] = NULL; - } - - // Run through all of the Zerocoin tests - LogTestResult("an RSA modulus can be generated", Test_GenRSAModulus); - LogTestResult("parameter sizes are correct", Test_CalcParamSizes); - LogTestResult("group/field parameters can be generated", Test_GenerateGroupParams); - LogTestResult("parameter generation is correct", Test_ParamGen); - LogTestResult("coins can be minted", Test_MintCoin); - LogTestResult("invalid coins will be rejected", Test_InvalidCoin); - LogTestResult("the accumulator works", Test_Accumulator); - LogTestResult("the commitment equality PoK works", Test_EqualityPoK); - LogTestResult("a minted coin can be spent", Test_MintAndSpend); - - std::cout << std::endl << "Average coin size is " << gCoinSize << " bytes." << std::endl; - std::cout << "Serial number size is " << gSerialNumberSize << " bytes." << std::endl; - std::cout << "Spend proof size is " << gProofSize << " bytes." << std::endl; - - // Summarize test results - if (gSuccessfulTests < gNumTests) { - std::cout << std::endl << "ERROR: SOME TESTS FAILED" << std::endl; - } - - // Clear any generated coins - for (uint32_t i = 0; i < TESTS_COINS_TO_ACCUMULATE; i++) { - delete gCoins[i]; - } - - std::cout << std::endl << gSuccessfulTests << " out of " << gNumTests << " tests passed." << std::endl << std::endl; - delete g_Params; -} - -BOOST_FIXTURE_TEST_SUITE(libzerocoin, TestingSetup) -BOOST_AUTO_TEST_CASE(libzerocoin_tests) -{ - std::cout << "libzerocoin v" << ZEROCOIN_VERSION_STRING << " test utility." << std::endl << std::endl; - - Test_RunAllTests(); -} -BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/net_tests.cpp b/src/test/net_tests.cpp new file mode 100644 index 000000000..289238ca4 --- /dev/null +++ b/src/test/net_tests.cpp @@ -0,0 +1,147 @@ +// Copyright (c) 2012-2016 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 "addrman.h" +#include "chainparams.h" +#include "hash.h" +#include "net.h" +#include "serialize.h" +#include "streams.h" + +#include "test/test_aezora.h" + +#include + +#include + +class CAddrManSerializationMock : public CAddrMan +{ +public: + virtual void Serialize(CDataStream& s) const = 0; + + //! Ensure that bucket placement is always the same for testing purposes. + void MakeDeterministic() + { + nKey.SetNull(); + SeedInsecureRand(true); + } +}; + +class CAddrManUncorrupted : public CAddrManSerializationMock +{ +public: + void Serialize(CDataStream& s) const + { + CAddrMan::Serialize(s); + } +}; + +class CAddrManCorrupted : public CAddrManSerializationMock +{ +public: + void Serialize(CDataStream& s) const + { + // Produces corrupt output that claims addrman has 20 addrs when it only has one addr. + unsigned char nVersion = 1; + s << nVersion; + s << ((unsigned char)32); + s << nKey; + s << 10; // nNew + s << 10; // nTried + + int nUBuckets = ADDRMAN_NEW_BUCKET_COUNT ^ (1 << 30); + s << nUBuckets; + + CAddress addr = CAddress(CService("252.1.1.1", 7777), NODE_NONE); + CAddrInfo info = CAddrInfo(addr, CNetAddr("252.2.2.2")); + s << info; + } +}; + +CDataStream AddrmanToStream(CAddrManSerializationMock& addrman) +{ + CDataStream ssPeersIn(SER_DISK, CLIENT_VERSION); + ssPeersIn << FLATDATA(Params().MessageStart()); + ssPeersIn << addrman; + std::string str = ssPeersIn.str(); + std::vector vchData(str.begin(), str.end()); + return CDataStream(vchData, SER_DISK, CLIENT_VERSION); +} + +BOOST_FIXTURE_TEST_SUITE(net_tests, BasicTestingSetup) + +BOOST_AUTO_TEST_CASE(caddrdb_read) +{ + CAddrManUncorrupted addrmanUncorrupted; + addrmanUncorrupted.MakeDeterministic(); + + CService addr1 = CService("250.7.1.1", 8333); + CService addr2 = CService("250.7.2.2", 9999); + CService addr3 = CService("250.7.3.3", 9999); + + // Add three addresses to new table. + addrmanUncorrupted.Add(CAddress(addr1, NODE_NONE), CService("252.5.1.1", 8333)); + addrmanUncorrupted.Add(CAddress(addr2, NODE_NONE), CService("252.5.1.1", 8333)); + addrmanUncorrupted.Add(CAddress(addr3, NODE_NONE), CService("252.5.1.1", 8333)); + + // Test that the de-serialization does not throw an exception. + CDataStream ssPeers1 = AddrmanToStream(addrmanUncorrupted); + bool exceptionThrown = false; + CAddrMan addrman1; + + BOOST_CHECK(addrman1.size() == 0); + try { + unsigned char pchMsgTmp[4]; + ssPeers1 >> FLATDATA(pchMsgTmp); + ssPeers1 >> addrman1; + } catch (const std::exception& e) { + exceptionThrown = true; + } + + BOOST_CHECK(addrman1.size() == 3); + BOOST_CHECK(exceptionThrown == false); + + // Test that CAddrDB::Read creates an addrman with the correct number of addrs. + CDataStream ssPeers2 = AddrmanToStream(addrmanUncorrupted); + + CAddrMan addrman2; + CAddrDB adb; + BOOST_CHECK(addrman2.size() == 0); + adb.Read(addrman2, ssPeers2); + BOOST_CHECK(addrman2.size() == 3); +} + + +BOOST_AUTO_TEST_CASE(caddrdb_read_corrupted) +{ + CAddrManCorrupted addrmanCorrupted; + addrmanCorrupted.MakeDeterministic(); + + // Test that the de-serialization of corrupted addrman throws an exception. + CDataStream ssPeers1 = AddrmanToStream(addrmanCorrupted); + bool exceptionThrown = false; + CAddrMan addrman1; + BOOST_CHECK(addrman1.size() == 0); + try { + unsigned char pchMsgTmp[4]; + ssPeers1 >> FLATDATA(pchMsgTmp); + ssPeers1 >> addrman1; + } catch (const std::exception& e) { + exceptionThrown = true; + } + // Even through de-serialization failed addrman is not left in a clean state. + BOOST_CHECK(addrman1.size() == 1); + BOOST_CHECK(exceptionThrown); + + // Test that CAddrDB::Read leaves addrman in a clean state if de-serialization fails. + CDataStream ssPeers2 = AddrmanToStream(addrmanCorrupted); + + CAddrMan addrman2; + CAddrDB adb; + BOOST_CHECK(addrman2.size() == 0); + adb.Read(addrman2, ssPeers2); + BOOST_CHECK(addrman2.size() == 0); +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/prevector_tests.cpp b/src/test/prevector_tests.cpp new file mode 100644 index 000000000..50f485bf0 --- /dev/null +++ b/src/test/prevector_tests.cpp @@ -0,0 +1,242 @@ +// Copyright (c) 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 +#include "prevector.h" +#include "random.h" + +#include "serialize.h" +#include "streams.h" + +#include "test/test_aezora.h" + +#include + +BOOST_FIXTURE_TEST_SUITE(PrevectorTests, TestingSetup) + +template +class prevector_tester { + typedef std::vector realtype; + realtype real_vector; + realtype real_vector_alt; + + typedef prevector pretype; + pretype pre_vector; + pretype pre_vector_alt; + + typedef typename pretype::size_type Size; + + void test() { + const pretype& const_pre_vector = pre_vector; + BOOST_CHECK_EQUAL(real_vector.size(), pre_vector.size()); + BOOST_CHECK_EQUAL(real_vector.empty(), pre_vector.empty()); + for (Size s = 0; s < real_vector.size(); s++) { + BOOST_CHECK(real_vector[s] == pre_vector[s]); + BOOST_CHECK(&(pre_vector[s]) == &(pre_vector.begin()[s])); + BOOST_CHECK(&(pre_vector[s]) == &*(pre_vector.begin() + s)); + BOOST_CHECK(&(pre_vector[s]) == &*((pre_vector.end() + s) - real_vector.size())); + } + // BOOST_CHECK(realtype(pre_vector) == real_vector); + BOOST_CHECK(pretype(real_vector.begin(), real_vector.end()) == pre_vector); + BOOST_CHECK(pretype(pre_vector.begin(), pre_vector.end()) == pre_vector); + size_t pos = 0; + for (const T& v : pre_vector) { + BOOST_CHECK(v == real_vector[pos++]); + } + pos = 0; + for (const T& v : const_pre_vector) { + BOOST_CHECK(v == real_vector[pos++]); + } + + CDataStream ss1(SER_DISK, 0); + CDataStream ss2(SER_DISK, 0); + ss1 << real_vector; + ss2 << pre_vector; + BOOST_CHECK_EQUAL(ss1.size(), ss2.size()); + for (Size s = 0; s < ss1.size(); s++) { + BOOST_CHECK_EQUAL(ss1[s], ss2[s]); + } + } + +public: + void resize(Size s) { + real_vector.resize(s); + BOOST_CHECK_EQUAL(real_vector.size(), s); + pre_vector.resize(s); + BOOST_CHECK_EQUAL(pre_vector.size(), s); + test(); + } + + void reserve(Size s) { + real_vector.reserve(s); + BOOST_CHECK(real_vector.capacity() >= s); + pre_vector.reserve(s); + BOOST_CHECK(pre_vector.capacity() >= s); + test(); + } + + void insert(Size position, const T& value) { + real_vector.insert(real_vector.begin() + position, value); + pre_vector.insert(pre_vector.begin() + position, value); + test(); + } + + void insert(Size position, Size count, const T& value) { + real_vector.insert(real_vector.begin() + position, count, value); + pre_vector.insert(pre_vector.begin() + position, count, value); + test(); + } + + template + void insert_range(Size position, I first, I last) { + real_vector.insert(real_vector.begin() + position, first, last); + pre_vector.insert(pre_vector.begin() + position, first, last); + test(); + } + + void erase(Size position) { + real_vector.erase(real_vector.begin() + position); + pre_vector.erase(pre_vector.begin() + position); + test(); + } + + void erase(Size first, Size last) { + real_vector.erase(real_vector.begin() + first, real_vector.begin() + last); + pre_vector.erase(pre_vector.begin() + first, pre_vector.begin() + last); + test(); + } + + void update(Size pos, const T& value) { + real_vector[pos] = value; + pre_vector[pos] = value; + test(); + } + + void push_back(const T& value) { + real_vector.push_back(value); + pre_vector.push_back(value); + test(); + } + + void pop_back() { + real_vector.pop_back(); + pre_vector.pop_back(); + test(); + } + + void clear() { + real_vector.clear(); + pre_vector.clear(); + } + + void assign(Size n, const T& value) { + real_vector.assign(n, value); + pre_vector.assign(n, value); + } + + Size size() { + return real_vector.size(); + } + + Size capacity() { + return pre_vector.capacity(); + } + + void shrink_to_fit() { + pre_vector.shrink_to_fit(); + test(); + } + + void swap() { + real_vector.swap(real_vector_alt); + pre_vector.swap(pre_vector_alt); + test(); + } + + void move() { + real_vector = std::move(real_vector_alt); + real_vector_alt.clear(); + pre_vector = std::move(pre_vector_alt); + pre_vector_alt.clear(); + } + + void copy() { + real_vector = real_vector_alt; + pre_vector = pre_vector_alt; + } +}; + +BOOST_AUTO_TEST_CASE(PrevectorTestInt) +{ + for (int j = 0; j < 64; j++) { + prevector_tester<8, int> test; + for (int i = 0; i < 2048; i++) { + int r = InsecureRand32(); + if ((r % 4) == 0) { + test.insert(InsecureRand32() % (test.size() + 1), InsecureRand32()); + } + if (test.size() > 0 && ((r >> 2) % 4) == 1) { + test.erase(InsecureRand32() % test.size()); + } + if (((r >> 4) % 8) == 2) { + int new_size = std::max(0, std::min(30, test.size() + (InsecureRand32() % 5) - 2)); + test.resize(new_size); + } + if (((r >> 7) % 8) == 3) { + test.insert(InsecureRand32() % (test.size() + 1), 1 + (InsecureRand32() % 2), InsecureRand32()); + } + if (((r >> 10) % 8) == 4) { + int del = std::min(test.size(), 1 + (InsecureRand32() % 2)); + int beg = InsecureRand32() % (test.size() + 1 - del); + test.erase(beg, beg + del); + } + if (((r >> 13) % 16) == 5) { + test.push_back(InsecureRand32()); + } + if (test.size() > 0 && ((r >> 17) % 16) == 6) { + test.pop_back(); + } + if (((r >> 21) % 32) == 7) { + int values[4]; + int num = 1 + (InsecureRand32() % 4); + for (int i = 0; i < num; i++) { + values[i] = InsecureRand32(); + } + test.insert_range(InsecureRand32() % (test.size() + 1), values, values + num); + } + if (((r >> 26) % 32) == 8) { + int del = std::min(test.size(), 1 + (InsecureRand32() % 4)); + int beg = InsecureRand32() % (test.size() + 1 - del); + test.erase(beg, beg + del); + } + r = InsecureRand32(); + if (r % 32 == 9) { + test.reserve(InsecureRand32() % 32); + } + if ((r >> 5) % 64 == 10) { + test.shrink_to_fit(); + } + if (test.size() > 0) { + test.update(InsecureRand32() % test.size(), InsecureRand32()); + } + if (((r >> 11) % 1024) == 11) { + test.clear(); + } + if (((r >> 21) % 512) == 12) { + test.assign(InsecureRand32() % 32, InsecureRand32()); + } + if (((r >> 15) % 8) == 3) { + test.swap(); + } + if (((r >> 15) % 16) == 8) { + test.copy(); + } + if (((r >> 15) % 32) == 18) { + test.move(); + } + } + } +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/rpc_wallet_tests.cpp b/src/test/rpc_wallet_tests.cpp deleted file mode 100644 index 2ef07c128..000000000 --- a/src/test/rpc_wallet_tests.cpp +++ /dev/null @@ -1,185 +0,0 @@ -// Copyright (c) 2013-2014 The Bitcoin Core developers -// Copyright (c) 2017-2019 The AEZORA developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#include "rpc/server.h" -#include "rpc/client.h" - -#include "base58.h" -#include "wallet/wallet.h" - -#include "test/test_aezora.h" - -#include -#include - -#include - - -extern UniValue createArgs(int nRequired, const char* address1 = NULL, const char* address2 = NULL); -extern UniValue CallRPC(std::string args); - -extern CWallet* pwalletMain; - -BOOST_FIXTURE_TEST_SUITE(rpc_wallet_tests, TestingSetup) - -BOOST_AUTO_TEST_CASE(rpc_addmultisig) -{ - LOCK(pwalletMain->cs_wallet); - - rpcfn_type addmultisig = tableRPC["addmultisigaddress"]->actor; - - // old, 65-byte-long: - const char address1Hex[] = "041431A18C7039660CD9E3612A2A47DC53B69CB38EA4AD743B7DF8245FD0438F8E7270415F1085B9DC4D7DA367C69F1245E27EE5552A481D6854184C80F0BB8456"; - // new, compressed: - const char address2Hex[] = "029BBEFF390CE736BD396AF43B52A1C14ED52C086B1E5585C15931F68725772BAC"; - - UniValue v; - CBitcoinAddress address; - BOOST_CHECK_NO_THROW(v = addmultisig(createArgs(1, address1Hex), false)); - address.SetString(v.get_str()); - BOOST_CHECK(address.IsValid() && address.IsScript()); - - BOOST_CHECK_NO_THROW(v = addmultisig(createArgs(1, address1Hex, address2Hex), false)); - address.SetString(v.get_str()); - BOOST_CHECK(address.IsValid() && address.IsScript()); - - BOOST_CHECK_NO_THROW(v = addmultisig(createArgs(2, address1Hex, address2Hex), false)); - address.SetString(v.get_str()); - BOOST_CHECK(address.IsValid() && address.IsScript()); - - BOOST_CHECK_THROW(addmultisig(createArgs(0), false), std::runtime_error); - BOOST_CHECK_THROW(addmultisig(createArgs(1), false), std::runtime_error); - BOOST_CHECK_THROW(addmultisig(createArgs(2, address1Hex), false), std::runtime_error); - - BOOST_CHECK_THROW(addmultisig(createArgs(1, ""), false), std::runtime_error); - BOOST_CHECK_THROW(addmultisig(createArgs(1, "NotAValidPubkey"), false), std::runtime_error); - - std::string short1(address1Hex, address1Hex + sizeof(address1Hex) - 2); // last byte missing - BOOST_CHECK_THROW(addmultisig(createArgs(2, short1.c_str()), false), std::runtime_error); - - std::string short2(address1Hex + 1, address1Hex + sizeof(address1Hex)); // first byte missing - BOOST_CHECK_THROW(addmultisig(createArgs(2, short2.c_str()), false), std::runtime_error); -} - -BOOST_AUTO_TEST_CASE(rpc_wallet) -{ - // Test RPC calls for various wallet statistics - UniValue r; - - LOCK2(cs_main, pwalletMain->cs_wallet); - - CPubKey demoPubkey = pwalletMain->GenerateNewKey(); - CBitcoinAddress demoAddress = CBitcoinAddress(CTxDestination(demoPubkey.GetID())); - UniValue retValue; - std::string strAccount = "walletDemoAccount"; - std::string strPurpose = "receive"; - BOOST_CHECK_NO_THROW({ /*Initialize Wallet with an account */ - CWalletDB walletdb(pwalletMain->strWalletFile); - CAccount account; - account.vchPubKey = demoPubkey; - pwalletMain->SetAddressBook(account.vchPubKey.GetID(), strAccount, strPurpose); - walletdb.WriteAccount(strAccount, account); - }); - - CPubKey setaccountDemoPubkey = pwalletMain->GenerateNewKey(); - CBitcoinAddress setaccountDemoAddress = CBitcoinAddress(CTxDestination(setaccountDemoPubkey.GetID())); - - /********************************* - * setaccount - *********************************/ - BOOST_CHECK_NO_THROW(CallRPC("setaccount " + setaccountDemoAddress.ToString() + " nullaccount")); - /* D8w12Vu3WVhn543dgrUUf9uYu6HLwnPm5R is not owned by the test wallet. */ - BOOST_CHECK_THROW(CallRPC("setaccount D8w12Vu3WVhn543dgrUUf9uYu6HLwnPm5R nullaccount"), std::runtime_error); - BOOST_CHECK_THROW(CallRPC("setaccount"), std::runtime_error); - /* D8w12Vu3WVhn543dgrUUf9uYu6HLwnPm5 (33 chars) is an illegal address (should be 34 chars) */ - BOOST_CHECK_THROW(CallRPC("setaccount D8w12Vu3WVhn543dgrUUf9uYu6HLwnPm5 nullaccount"), std::runtime_error); - - /********************************* - * listunspent - *********************************/ - BOOST_CHECK_NO_THROW(CallRPC("listunspent")); - BOOST_CHECK_THROW(CallRPC("listunspent string"), std::runtime_error); - BOOST_CHECK_THROW(CallRPC("listunspent 0 string"), std::runtime_error); - BOOST_CHECK_THROW(CallRPC("listunspent 0 1 not_array"), std::runtime_error); - BOOST_CHECK_THROW(CallRPC("listunspent 0 1 [] extra"), std::runtime_error); - BOOST_CHECK_NO_THROW(r = CallRPC("listunspent 0 1 []")); - BOOST_CHECK(r.get_array().empty()); - - /********************************* - * listreceivedbyaddress - *********************************/ - BOOST_CHECK_NO_THROW(CallRPC("listreceivedbyaddress")); - BOOST_CHECK_NO_THROW(CallRPC("listreceivedbyaddress 0")); - BOOST_CHECK_THROW(CallRPC("listreceivedbyaddress not_int"), std::runtime_error); - BOOST_CHECK_THROW(CallRPC("listreceivedbyaddress 0 not_bool"), std::runtime_error); - BOOST_CHECK_NO_THROW(CallRPC("listreceivedbyaddress 0 true")); - BOOST_CHECK_THROW(CallRPC("listreceivedbyaddress 0 true extra"), std::runtime_error); - - /********************************* - * listreceivedbyaccount - *********************************/ - BOOST_CHECK_NO_THROW(CallRPC("listreceivedbyaccount")); - BOOST_CHECK_NO_THROW(CallRPC("listreceivedbyaccount 0")); - BOOST_CHECK_THROW(CallRPC("listreceivedbyaccount not_int"), std::runtime_error); - BOOST_CHECK_THROW(CallRPC("listreceivedbyaccount 0 not_bool"), std::runtime_error); - BOOST_CHECK_NO_THROW(CallRPC("listreceivedbyaccount 0 true")); - BOOST_CHECK_THROW(CallRPC("listreceivedbyaccount 0 true extra"), std::runtime_error); - - /********************************* - * getrawchangeaddress - *********************************/ - BOOST_CHECK_NO_THROW(CallRPC("getrawchangeaddress")); - - /********************************* - * getnewaddress - *********************************/ - BOOST_CHECK_NO_THROW(CallRPC("getnewaddress")); - BOOST_CHECK_NO_THROW(CallRPC("getnewaddress getnewaddress_demoaccount")); - - /********************************* - * getaccountaddress - *********************************/ - BOOST_CHECK_NO_THROW(CallRPC("getaccountaddress \"\"")); - BOOST_CHECK_NO_THROW(CallRPC("getaccountaddress accountThatDoesntExists")); // Should generate a new account - BOOST_CHECK_NO_THROW(retValue = CallRPC("getaccountaddress " + strAccount)); - BOOST_CHECK(CBitcoinAddress(retValue.get_str()).Get() == demoAddress.Get()); - - /********************************* - * getaccount - *********************************/ - BOOST_CHECK_THROW(CallRPC("getaccount"), std::runtime_error); - BOOST_CHECK_NO_THROW(CallRPC("getaccount " + demoAddress.ToString())); - - /********************************* - * signmessage + verifymessage - *********************************/ - BOOST_CHECK_NO_THROW(retValue = CallRPC("signmessage " + demoAddress.ToString() + " mymessage")); - BOOST_CHECK_THROW(CallRPC("signmessage"), std::runtime_error); - /* Should throw error because this address is not loaded in the wallet */ - BOOST_CHECK_THROW(CallRPC("signmessage D8w12Vu3WVhn543dgrUUf9uYu6HLwnPm5R mymessage"), std::runtime_error); - - /* missing arguments */ - BOOST_CHECK_THROW(CallRPC("verifymessage " + demoAddress.ToString()), std::runtime_error); - BOOST_CHECK_THROW(CallRPC("verifymessage " + demoAddress.ToString() + " " + retValue.get_str()), std::runtime_error); - /* Illegal address */ - BOOST_CHECK_THROW(CallRPC("verifymessage D8w12Vu3WVhn543dgrUUf9uYu6HLwnPm5 " + retValue.get_str() + " mymessage"), std::runtime_error); - /* wrong address */ - BOOST_CHECK(CallRPC("verifymessage D8w12Vu3WVhn543dgrUUf9uYu6HLwnPm5R " + retValue.get_str() + " mymessage").get_bool() == false); - /* Correct address and signature but wrong message */ - BOOST_CHECK(CallRPC("verifymessage " + demoAddress.ToString() + " " + retValue.get_str() + " wrongmessage").get_bool() == false); - /* Correct address, message and signature*/ - BOOST_CHECK(CallRPC("verifymessage " + demoAddress.ToString() + " " + retValue.get_str() + " mymessage").get_bool() == true); - - /********************************* - * getaddressesbyaccount - *********************************/ - BOOST_CHECK_THROW(CallRPC("getaddressesbyaccount"), std::runtime_error); - BOOST_CHECK_NO_THROW(retValue = CallRPC("getaddressesbyaccount " + strAccount)); - UniValue arr = retValue.get_array(); - BOOST_CHECK(arr.size() > 0); - BOOST_CHECK(CBitcoinAddress(arr[0].get_str()).Get() == demoAddress.Get()); -} - -BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/sync_tests.cpp b/src/test/sync_tests.cpp new file mode 100644 index 000000000..fab348c4c --- /dev/null +++ b/src/test/sync_tests.cpp @@ -0,0 +1,52 @@ +// Copyright (c) 2012-2020 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 "sync.h" +#include "test/test_aezora.h" + +#include + +namespace { +template +void TestPotentialDeadLockDetected(MutexType& mutex1, MutexType& mutex2) +{ + { + LOCK2(mutex1, mutex2); + } + bool error_thrown = false; + try { + LOCK2(mutex2, mutex1); + } catch (const std::logic_error& e) { + BOOST_CHECK_EQUAL(e.what(), "potential deadlock detected"); + error_thrown = true; + } + #ifdef DEBUG_LOCKORDER + BOOST_CHECK(error_thrown); + #else + BOOST_CHECK(!error_thrown); + #endif +} +} // namespace + +BOOST_FIXTURE_TEST_SUITE(sync_tests, BasicTestingSetup) + +BOOST_AUTO_TEST_CASE(potential_deadlock_detected) +{ + #ifdef DEBUG_LOCKORDER + bool prev = g_debug_lockorder_abort; + g_debug_lockorder_abort = false; + #endif + + RecursiveMutex rmutex1, rmutex2; + TestPotentialDeadLockDetected(rmutex1, rmutex2); + + Mutex mutex1, mutex2; + TestPotentialDeadLockDetected(mutex1, mutex2); + + #ifdef DEBUG_LOCKORDER + g_debug_lockorder_abort = prev; + #endif +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/src/txdb.cpp b/src/txdb.cpp index 941bbfa58..8366b0161 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -14,19 +14,17 @@ #include +static const char DB_COINS = 'c'; +static const char DB_BLOCK_FILES = 'f'; +static const char DB_TXINDEX = 't'; +static const char DB_BLOCK_INDEX = 'b'; -void static BatchWriteCoins(CLevelDBBatch& batch, const uint256& hash, const CCoins& coins) -{ - if (coins.IsPruned()) - batch.Erase(std::make_pair('c', hash)); - else - batch.Write(std::make_pair('c', hash), coins); -} +static const char DB_BEST_BLOCK = 'B'; +static const char DB_FLAG = 'F'; +static const char DB_REINDEX_FLAG = 'R'; +static const char DB_LAST_BLOCK = 'l'; +static const char DB_MONEY_SUPPLY = 'M'; -void static BatchWriteHashBestChain(CLevelDBBatch& batch, const uint256& hash) -{ - batch.Write('B', hash); -} CCoinsViewDB::CCoinsViewDB(size_t nCacheSize, bool fMemory, bool fWipe) : db(GetDataDir() / "chainstate", nCacheSize, fMemory, fWipe) { @@ -34,30 +32,33 @@ CCoinsViewDB::CCoinsViewDB(size_t nCacheSize, bool fMemory, bool fWipe) : db(Get bool CCoinsViewDB::GetCoins(const uint256& txid, CCoins& coins) const { - return db.Read(std::make_pair('c', txid), coins); + return db.Read(std::make_pair(DB_COINS, txid), coins); } bool CCoinsViewDB::HaveCoins(const uint256& txid) const { - return db.Exists(std::make_pair('c', txid)); + return db.Exists(std::make_pair(DB_COINS, txid)); } uint256 CCoinsViewDB::GetBestBlock() const { uint256 hashBestChain; - if (!db.Read('B', hashBestChain)) + if (!db.Read(DB_BEST_BLOCK, hashBestChain)) return UINT256_ZERO; return hashBestChain; } bool CCoinsViewDB::BatchWrite(CCoinsMap& mapCoins, const uint256& hashBlock) { - CLevelDBBatch batch; + CDBBatch batch; size_t count = 0; size_t changed = 0; for (CCoinsMap::iterator it = mapCoins.begin(); it != mapCoins.end();) { if (it->second.flags & CCoinsCacheEntry::DIRTY) { - BatchWriteCoins(batch, it->first, it->second.coins); + if (it->second.coins.IsPruned()) + batch.Erase(std::make_pair(DB_COINS, it->first)); + else + batch.Write(std::make_pair(DB_COINS, it->first), it->second.coins); changed++; } count++; @@ -65,43 +66,43 @@ bool CCoinsViewDB::BatchWrite(CCoinsMap& mapCoins, const uint256& hashBlock) mapCoins.erase(itOld); } if (!hashBlock.IsNull()) - BatchWriteHashBestChain(batch, hashBlock); + batch.Write(DB_BEST_BLOCK, hashBlock); LogPrint(BCLog::COINDB, "Committing %u changed transactions (out of %u) to coin database...\n", (unsigned int)changed, (unsigned int)count); return db.WriteBatch(batch); } -CBlockTreeDB::CBlockTreeDB(size_t nCacheSize, bool fMemory, bool fWipe) : CLevelDBWrapper(GetDataDir() / "blocks" / "index", nCacheSize, fMemory, fWipe) +CBlockTreeDB::CBlockTreeDB(size_t nCacheSize, bool fMemory, bool fWipe) : CDBWrapper(GetDataDir() / "blocks" / "index", nCacheSize, fMemory, fWipe) { } bool CBlockTreeDB::WriteBlockIndex(const CDiskBlockIndex& blockindex) { - return Write(std::make_pair('b', blockindex.GetBlockHash()), blockindex); + return Write(std::make_pair(DB_BLOCK_INDEX, blockindex.GetBlockHash()), blockindex); } bool CBlockTreeDB::ReadBlockFileInfo(int nFile, CBlockFileInfo& info) { - return Read(std::make_pair('f', nFile), info); + return Read(std::make_pair(DB_BLOCK_FILES, nFile), info); } bool CBlockTreeDB::WriteReindexing(bool fReindexing) { if (fReindexing) - return Write('R', '1'); + return Write(DB_REINDEX_FLAG, '1'); else - return Erase('R'); + return Erase(DB_REINDEX_FLAG); } bool CBlockTreeDB::ReadReindexing(bool& fReindexing) { - fReindexing = Exists('R'); + fReindexing = Exists(DB_REINDEX_FLAG); return true; } bool CBlockTreeDB::ReadLastBlockFile(int& nFile) { - return Read('l', nFile); + return Read(DB_LAST_BLOCK, nFile); } bool CCoinsViewDB::GetStats(CCoinsStats& stats) const @@ -109,8 +110,8 @@ bool CCoinsViewDB::GetStats(CCoinsStats& stats) const /* It seems that there are no "const iterators" for LevelDB. Since we only need read operations on it, use a const-cast to get around that restriction. */ - boost::scoped_ptr pcursor(const_cast(&db)->NewIterator()); - pcursor->SeekToFirst(); + boost::scoped_ptr pcursor(const_cast(&db)->NewIterator()); + pcursor->Seek(DB_COINS); CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION); stats.hashBlock = GetBestBlock(); @@ -118,22 +119,10 @@ bool CCoinsViewDB::GetStats(CCoinsStats& stats) const CAmount nTotalAmount = 0; while (pcursor->Valid()) { boost::this_thread::interruption_point(); - try { - leveldb::Slice slKey = pcursor->key(); - CDataStream ssKey(slKey.data(), slKey.data() + slKey.size(), SER_DISK, CLIENT_VERSION); - char chType; - ssKey >> chType; - if (chType == 'c') { - leveldb::Slice slValue = pcursor->value(); - CDataStream ssValue(slValue.data(), slValue.data() + slValue.size(), SER_DISK, CLIENT_VERSION); - CCoins coins; - ssValue >> coins; - uint256 txhash; - ssKey >> txhash; - ss << txhash; - ss << VARINT(coins.nVersion); - ss << (coins.fCoinBase ? 'c' : 'n'); - ss << VARINT(coins.nHeight); + std::pair key; + CCoins coins; + if (pcursor->GetKey(key) && key.first == DB_COINS) { + if (pcursor->GetValue(coins)) { stats.nTransactions++; for (unsigned int i = 0; i < coins.vout.size(); i++) { const CTxOut& out = coins.vout[i]; @@ -144,66 +133,67 @@ bool CCoinsViewDB::GetStats(CCoinsStats& stats) const nTotalAmount += out.nValue; } } - stats.nSerializedSize += 32 + slValue.size(); + stats.nSerializedSize += 32 + pcursor->GetValueSize(); ss << VARINT(0); + } else { + return error("CCoinsViewDB::GetStats() : unable to read value"); } - pcursor->Next(); - } catch (const std::exception& e) { - return error("%s : Deserialize or I/O error - %s", __func__, e.what()); + } else { + break; } + pcursor->Next(); } - stats.nHeight = mapBlockIndex.find(GetBestBlock())->second->nHeight; + + stats.nHeight = WITH_LOCK(cs_main, return mapBlockIndex.find(stats.hashBlock)->second->nHeight;); stats.hashSerialized = ss.GetHash(); stats.nTotalAmount = nTotalAmount; return true; } -static const char MONEYSUPPLY = 'M'; - bool CBlockTreeDB::WriteMoneySupply(const int64_t& nSupply) { - return Write(MONEYSUPPLY, nSupply); + return Write(DB_MONEY_SUPPLY, nSupply); } bool CBlockTreeDB::ReadMoneySupply(int64_t& nSupply) const { - return Read(MONEYSUPPLY, nSupply); + return Read(DB_MONEY_SUPPLY, nSupply); } bool CBlockTreeDB::WriteBatchSync(const std::vector >& fileInfo, int nLastFile, const std::vector& blockinfo) { - CLevelDBBatch batch; + CDBBatch batch; for (std::vector >::const_iterator it=fileInfo.begin(); it != fileInfo.end(); it++) { - batch.Write(std::make_pair('f', it->first), *it->second); + batch.Write(std::make_pair(DB_BLOCK_FILES, it->first), *it->second); } - batch.Write('l', nLastFile); + batch.Write(DB_LAST_BLOCK, nLastFile); for (std::vector::const_iterator it=blockinfo.begin(); it != blockinfo.end(); it++) { - batch.Write(std::make_pair('b', (*it)->GetBlockHash()), CDiskBlockIndex(*it)); + batch.Write(std::make_pair(DB_BLOCK_INDEX, (*it)->GetBlockHash()), CDiskBlockIndex(*it)); } return WriteBatch(batch, true); } bool CBlockTreeDB::ReadTxIndex(const uint256& txid, CDiskTxPos& pos) { - return Read(std::make_pair('t', txid), pos); + return Read(std::make_pair(DB_TXINDEX, txid), pos); } bool CBlockTreeDB::WriteTxIndex(const std::vector >& vect) { - CLevelDBBatch batch; + CDBBatch batch; for (std::vector >::const_iterator it = vect.begin(); it != vect.end(); it++) - batch.Write(std::make_pair('t', it->first), it->second); + batch.Write(std::make_pair(DB_TXINDEX, it->first), it->second); return WriteBatch(batch); } bool CBlockTreeDB::WriteFlag(const std::string& name, bool fValue) { - return Write(std::make_pair('F', name), fValue ? '1' : '0'); + return Write(std::make_pair(DB_FLAG, name), fValue ? '1' : '0'); } bool CBlockTreeDB::ReadFlag(const std::string& name, bool& fValue) { char ch; - if (!Read(std::make_pair('F', name), ch)) + if (!Read(std::make_pair(DB_FLAG, name), ch)) return false; fValue = ch == '1'; return true; @@ -221,26 +211,17 @@ bool CBlockTreeDB::ReadInt(const std::string& name, int& nValue) bool CBlockTreeDB::LoadBlockIndexGuts() { - boost::scoped_ptr pcursor(NewIterator()); + boost::scoped_ptr pcursor(NewIterator()); - CDataStream ssKeySet(SER_DISK, CLIENT_VERSION); - ssKeySet << std::make_pair('b', UINT256_ZERO); - pcursor->Seek(ssKeySet.str()); + pcursor->Seek(std::make_pair(DB_BLOCK_INDEX, UINT256_ZERO)); // Load mapBlockIndex while (pcursor->Valid()) { boost::this_thread::interruption_point(); - try { - leveldb::Slice slKey = pcursor->key(); - CDataStream ssKey(slKey.data(), slKey.data() + slKey.size(), SER_DISK, CLIENT_VERSION); - char chType; - ssKey >> chType; - if (chType == 'b') { - leveldb::Slice slValue = pcursor->value(); - CDataStream ssValue(slValue.data(), slValue.data() + slValue.size(), SER_DISK, CLIENT_VERSION); - CDiskBlockIndex diskindex; - ssValue >> diskindex; - + std::pair key; + if (pcursor->GetKey(key) && key.first == DB_BLOCK_INDEX) { + CDiskBlockIndex diskindex; + if (pcursor->GetValue(diskindex)) { // Construct block index object CBlockIndex* pindexNew = InsertBlockIndex(diskindex.GetBlockHash()); pindexNew->pprev = InsertBlockIndex(diskindex.hashPrev); @@ -270,10 +251,10 @@ bool CBlockTreeDB::LoadBlockIndexGuts() pcursor->Next(); } else { - break; // if shutdown requested or finished loading block index + return error("%s : failed to read value", __func__); } - } catch (const std::exception& e) { - return error("%s : Deserialize or I/O error - %s", __func__, e.what()); + } else { + break; } } @@ -282,16 +263,16 @@ bool CBlockTreeDB::LoadBlockIndexGuts() bool CBlockTreeDB::ReadLegacyBlockIndex(const uint256& blockHash, CLegacyBlockIndex& biRet) { - return Read(std::make_pair('b', blockHash), biRet); + return Read(std::make_pair(DB_BLOCK_INDEX, blockHash), biRet); } -CZerocoinDB::CZerocoinDB(size_t nCacheSize, bool fMemory, bool fWipe) : CLevelDBWrapper(GetDataDir() / "zerocoin", nCacheSize, fMemory, fWipe) +CZerocoinDB::CZerocoinDB(size_t nCacheSize, bool fMemory, bool fWipe) : CDBWrapper(GetDataDir() / "zerocoin", nCacheSize, fMemory, fWipe) { } bool CZerocoinDB::WriteCoinMintBatch(const std::vector >& mintInfo) { - CLevelDBBatch batch; + CDBBatch batch; size_t count = 0; for (std::vector >::const_iterator it=mintInfo.begin(); it != mintInfo.end(); it++) { libzerocoin::PublicCoin pubCoin = it->first; @@ -322,7 +303,7 @@ bool CZerocoinDB::EraseCoinMint(const CBigNum& bnPubcoin) bool CZerocoinDB::WriteCoinSpendBatch(const std::vector >& spendInfo) { - CLevelDBBatch batch; + CDBBatch batch; size_t count = 0; for (std::vector >::const_iterator it=spendInfo.begin(); it != spendInfo.end(); it++) { CBigNum bnSerial = it->first.getCoinSerialNumber(); @@ -365,33 +346,25 @@ bool CZerocoinDB::WipeCoins(std::string strType) if (strType != "spends" && strType != "mints") return error("%s: did not recognize type %s", __func__, strType); - boost::scoped_ptr pcursor(NewIterator()); + boost::scoped_ptr pcursor(NewIterator()); char type = (strType == "spends" ? 's' : 'm'); - CDataStream ssKeySet(SER_DISK, CLIENT_VERSION); - ssKeySet << std::make_pair(type, UINT256_ZERO); - pcursor->Seek(ssKeySet.str()); + pcursor->Seek(std::make_pair(type, UINT256_ZERO)); // Load mapBlockIndex std::set setDelete; while (pcursor->Valid()) { boost::this_thread::interruption_point(); - try { - leveldb::Slice slKey = pcursor->key(); - CDataStream ssKey(slKey.data(), slKey.data() + slKey.size(), SER_DISK, CLIENT_VERSION); - char chType; - ssKey >> chType; - if (chType == type) { - leveldb::Slice slValue = pcursor->value(); - CDataStream ssValue(slValue.data(), slValue.data() + slValue.size(), SER_DISK, CLIENT_VERSION); - uint256 hash; - ssValue >> hash; + std::pair key; + if (pcursor->GetKey(key) && key.first == type) { + uint256 hash; + if (pcursor->GetValue(hash)) { setDelete.insert(hash); pcursor->Next(); } else { - break; // if shutdown requested or finished loading block index + return error("%s : failed to read value", __func__); } - } catch (const std::exception& e) { - return error("%s : Deserialize or I/O error - %s", __func__, e.what()); + } else { + break; } } @@ -435,28 +408,22 @@ bool CZerocoinDB::EraseAccChecksum(const uint32_t& nChecksum, const libzerocoin: bool CZerocoinDB::WipeAccChecksums() { - boost::scoped_ptr pcursor(NewIterator()); - CDataStream ssKeySet(SER_DISK, CLIENT_VERSION); - ssKeySet << std::make_pair(LZC_ACCUMCS, (uint32_t) 0); - pcursor->Seek(ssKeySet.str()); + boost::scoped_ptr pcursor(NewIterator()); + pcursor->Seek(std::make_pair(LZC_ACCUMCS, (uint32_t) 0)); std::set setDelete; while (pcursor->Valid()) { boost::this_thread::interruption_point(); - try { - leveldb::Slice slKey = pcursor->key(); - CDataStream ssKey(slKey.data(), slKey.data() + slKey.size(), SER_DISK, CLIENT_VERSION); - char chType; - ssKey >> chType; - if (chType == LZC_ACCUMCS) { - leveldb::Slice slValue = pcursor->value(); - CDataStream ssValue(slValue.data(), slValue.data() + slValue.size(), SER_DISK, CLIENT_VERSION); - uint32_t acs; - ssValue >> acs; + std::pair key; + if (pcursor->GetKey(key) && key.first == LZC_ACCUMCS) { + uint32_t acs; + if (pcursor->GetValue(acs)) { setDelete.insert(acs); pcursor->Next(); - } else break; - } catch (const std::exception& e) { - return error("%s : Deserialize or I/O error - %s", __func__, e.what()); + } else { + return error("%s : failed to read value", __func__); + } + } else { + break; } } diff --git a/src/txdb.h b/src/txdb.h index 3ca25be8e..96b092a0b 100644 --- a/src/txdb.h +++ b/src/txdb.h @@ -7,7 +7,7 @@ #ifndef BITCOIN_TXDB_H #define BITCOIN_TXDB_H -#include "leveldbwrapper.h" +#include "dbwrapper.h" #include "main.h" #include "zazr/zerocoin.h" @@ -32,7 +32,7 @@ struct CDiskTxPos : public CDiskBlockPos { ADD_SERIALIZE_METHODS; template - inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) + inline void SerializationOp(Stream& s, Operation ser_action) { READWRITE(*(CDiskBlockPos*)this); READWRITE(VARINT(nTxOffset)); @@ -58,7 +58,7 @@ struct CDiskTxPos : public CDiskBlockPos { class CCoinsViewDB : public CCoinsView { protected: - CLevelDBWrapper db; + CDBWrapper db; public: CCoinsViewDB(size_t nCacheSize, bool fMemory = false, bool fWipe = false); @@ -71,7 +71,7 @@ class CCoinsViewDB : public CCoinsView }; /** Access to the block database (blocks/index/) */ -class CBlockTreeDB : public CLevelDBWrapper +class CBlockTreeDB : public CDBWrapper { public: CBlockTreeDB(size_t nCacheSize, bool fMemory = false, bool fWipe = false); @@ -100,7 +100,7 @@ class CBlockTreeDB : public CLevelDBWrapper }; /** Zerocoin database (zerocoin/) */ -class CZerocoinDB : public CLevelDBWrapper +class CZerocoinDB : public CDBWrapper { public: CZerocoinDB(size_t nCacheSize, bool fMemory = false, bool fWipe = false); diff --git a/src/undo.h b/src/undo.h index c2a3436d3..685e2063f 100644 --- a/src/undo.h +++ b/src/undo.h @@ -30,33 +30,26 @@ class CTxInUndo CTxInUndo() : txout(), fCoinBase(false), fCoinStake(false), nHeight(0), nVersion(0) {} CTxInUndo(const CTxOut& txoutIn, bool fCoinBaseIn = false, bool fCoinStakeIn = false, unsigned int nHeightIn = 0, int nVersionIn = 0) : txout(txoutIn), fCoinBase(fCoinBaseIn), fCoinStake(fCoinStakeIn), nHeight(nHeightIn), nVersion(nVersionIn) {} - unsigned int GetSerializeSize(int nType, int nVersion) const - { - return ::GetSerializeSize(VARINT(nHeight * 4 + (fCoinBase ? 2 : 0) + (fCoinStake ? 1 : 0)), nType, nVersion) + - (nHeight > 0 ? ::GetSerializeSize(VARINT(this->nVersion), nType, nVersion) : 0) + - ::GetSerializeSize(CTxOutCompressor(REF(txout)), nType, nVersion); - } - template - void Serialize(Stream& s, int nType, int nVersion) const + void Serialize(Stream& s) const { - ::Serialize(s, VARINT(nHeight * 4 + (fCoinBase ? 2 : 0) + (fCoinStake ? 1 : 0)), nType, nVersion); + ::Serialize(s, VARINT(nHeight * 4 + (fCoinBase ? 2 : 0) + (fCoinStake ? 1 : 0))); if (nHeight > 0) - ::Serialize(s, VARINT(this->nVersion), nType, nVersion); - ::Serialize(s, CTxOutCompressor(REF(txout)), nType, nVersion); + ::Serialize(s, VARINT(this->nVersion)); + ::Serialize(s, CTxOutCompressor(REF(txout))); } template - void Unserialize(Stream& s, int nType, int nVersion) + void Unserialize(Stream& s) { unsigned int nCode = 0; - ::Unserialize(s, VARINT(nCode), nType, nVersion); + ::Unserialize(s, VARINT(nCode)); nHeight = nCode >> 2; fCoinBase = nCode & 2; fCoinStake = nCode & 1; if (nHeight > 0) - ::Unserialize(s, VARINT(this->nVersion), nType, nVersion); - ::Unserialize(s, REF(CTxOutCompressor(REF(txout))), nType, nVersion); + ::Unserialize(s, VARINT(this->nVersion)); + ::Unserialize(s, REF(CTxOutCompressor(REF(txout)))); } }; @@ -70,7 +63,7 @@ class CTxUndo ADD_SERIALIZE_METHODS; template - inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) + inline void SerializationOp(Stream& s, Operation ser_action) { READWRITE(vprevout); } @@ -85,7 +78,7 @@ class CBlockUndo ADD_SERIALIZE_METHODS; template - inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) + inline void SerializationOp(Stream& s, Operation ser_action) { READWRITE(vtxundo); } diff --git a/src/version.h b/src/version.h index 7ffbd1a69..dbc95fd50 100644 --- a/src/version.h +++ b/src/version.h @@ -11,7 +11,7 @@ * network protocol versioning */ -static const int PROTOCOL_VERSION = 70922; +static const int PROTOCOL_VERSION = 70923; //! initial proto version, to be increased after version/verack negotiation static const int INIT_PROTO_VERSION = 209; @@ -20,8 +20,8 @@ static const int INIT_PROTO_VERSION = 209; static const int GETHEADERS_VERSION = 70077; //! disconnect from peers older than this proto version -static const int MIN_PEER_PROTO_VERSION_BEFORE_ENFORCEMENT = 70920; -static const int MIN_PEER_PROTO_VERSION_AFTER_ENFORCEMENT = 70922; +static const int MIN_PEER_PROTO_VERSION_BEFORE_ENFORCEMENT = 70922; +static const int MIN_PEER_PROTO_VERSION_AFTER_ENFORCEMENT = 70923; //! masternodes older than this proto version use old strMessage format for mnannounce static const int MIN_PEER_MNANNOUNCE = 70913; diff --git a/src/wallet/hdchain.h b/src/wallet/hdchain.h index db56efd6c..13dbfef96 100644 --- a/src/wallet/hdchain.h +++ b/src/wallet/hdchain.h @@ -34,9 +34,9 @@ class CHDChain ADD_SERIALIZE_METHODS; template - inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) + inline void SerializationOp(Stream& s, Operation ser_action) { - READWRITE(this->nVersion); + READWRITE(nVersion); READWRITE(seed_id); // Single account counters. READWRITE(nExternalChainCounter); diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 3996f2f8c..49eb1bbd1 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -3832,7 +3832,7 @@ extern UniValue DoZazrSpend(const CAmount nAmount, std::vector& v //construct JSON to return UniValue ret(UniValue::VOBJ); ret.push_back(Pair("txid", wtx.GetHash().ToString())); - ret.push_back(Pair("bytes", (int64_t)wtx.GetSerializeSize(SER_NETWORK, CTransaction::CURRENT_VERSION))); + ret.push_back(Pair("bytes", (int64_t)GetSerializeSize(wtx, SER_NETWORK, CTransaction::CURRENT_VERSION))); ret.push_back(Pair("fee", ValueFromAmount(nValueIn - nValueOut))); ret.push_back(Pair("duration_millis", (GetTimeMillis() - nTimeStart))); ret.push_back(Pair("spends", arrSpends)); diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index fccf80564..2ea315ff4 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1680,7 +1680,7 @@ int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate, b ret++; } - //If this is a zapwallettx, need to readd zpiv + //If this is a zapwallettx, need to readd zazr if (fCheckZAZR && pindex->nHeight >= Params().GetConsensus().height_start_ZC) { std::list listMints; BlockToZerocoinMintList(block, listMints, true); @@ -2597,7 +2597,7 @@ bool CWallet::CreateCoinStake( return false; } - // Parse utxos into CPivStakes + // Parse utxos into CAzrStakes std::list > listInputs; for (const COutput &out : vCoins) { std::unique_ptr input(new CAzrStake()); diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 7a04a8dac..6be292ab0 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -153,9 +153,10 @@ class CKeyPool ADD_SERIALIZE_METHODS; template - inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) + inline void SerializationOp(Stream& s, Operation ser_action) { - if (!(nType & SER_GETHASH)) + int nVersion = s.GetVersion(); + if (!(s.GetType() & SER_GETHASH)) READWRITE(nVersion); READWRITE(nTime); READWRITE(vchPubKey); @@ -722,11 +723,10 @@ class CMerkleTx : public CTransaction ADD_SERIALIZE_METHODS; template - inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) + inline void SerializationOp(Stream& s, Operation ser_action) { std::vector vMerkleBranch; // For compatibility with older versions. READWRITE(*(CTransaction*)this); - nVersion = this->nVersion; READWRITE(hashBlock); READWRITE(vMerkleBranch); READWRITE(nIndex); @@ -815,7 +815,7 @@ class CWalletTx : public CMerkleTx ADD_SERIALIZE_METHODS; template - inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) + inline void SerializationOp(Stream& s, Operation ser_action) { if (ser_action.ForRead()) Init(NULL); @@ -957,9 +957,10 @@ class CWalletKey ADD_SERIALIZE_METHODS; template - inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) + inline void SerializationOp(Stream& s, Operation ser_action) { - if (!(nType & SER_GETHASH)) + int nVersion = s.GetVersion(); + if (!(s.GetType() & SER_GETHASH)) READWRITE(nVersion); READWRITE(vchPrivKey); READWRITE(nTimeCreated); @@ -991,9 +992,10 @@ class CAccount ADD_SERIALIZE_METHODS; template - inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) + inline void SerializationOp(Stream& s, Operation ser_action) { - if (!(nType & SER_GETHASH)) + int nVersion = s.GetVersion(); + if (!(s.GetType() & SER_GETHASH)) READWRITE(nVersion); READWRITE(vchPubKey); } @@ -1035,9 +1037,10 @@ class CAccountingEntry ADD_SERIALIZE_METHODS; template - inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) + inline void SerializationOp(Stream& s, Operation ser_action) { - if (!(nType & SER_GETHASH)) + int nVersion = s.GetVersion(); + if (!(s.GetType() & SER_GETHASH)) READWRITE(nVersion); //! Note: strAccount is serialized as part of the key, not here. READWRITE(nCreditDebit); @@ -1048,7 +1051,7 @@ class CAccountingEntry WriteOrderPos(nOrderPos, mapValue); if (!(mapValue.empty() && _ssExtra.empty())) { - CDataStream ss(nType, nVersion); + CDataStream ss(s.GetType(), s.GetVersion()); ss.insert(ss.begin(), '\0'); ss << mapValue; ss.insert(ss.end(), _ssExtra.begin(), _ssExtra.end()); @@ -1062,7 +1065,7 @@ class CAccountingEntry if (ser_action.ForRead()) { mapValue.clear(); if (std::string::npos != nSepPos) { - CDataStream ss(std::vector(strComment.begin() + nSepPos + 1, strComment.end()), nType, nVersion); + CDataStream ss(std::vector(strComment.begin() + nSepPos + 1, strComment.end()), s.GetType(), s.GetVersion()); ss >> mapValue; _ssExtra = std::vector(ss.begin(), ss.end()); } diff --git a/src/wallet/wallet_zerocoin.cpp b/src/wallet/wallet_zerocoin.cpp index b7b433813..a7d22c574 100644 --- a/src/wallet/wallet_zerocoin.cpp +++ b/src/wallet/wallet_zerocoin.cpp @@ -265,7 +265,7 @@ bool CWallet::CreateZerocoinMintTransaction(const CAmount nValue, //any change that is less than 0.0100000 will be ignored and given as an extra fee - //also assume that a zerocoinspend that is minting the change will not have any change that goes to Piv + //also assume that a zerocoinspend that is minting the change will not have any change that goes to Azr CAmount nChange = nValueIn - nTotalValue; // Fee already accounted for in nTotalValue if (nChange > 1 * CENT) { // Fill a vout to ourself using the largest contributing address diff --git a/src/wallet/walletdb.h b/src/wallet/walletdb.h index ac37e3139..09a9ecce9 100644 --- a/src/wallet/walletdb.h +++ b/src/wallet/walletdb.h @@ -75,9 +75,9 @@ class CKeyMetadata ADD_SERIALIZE_METHODS; template - inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) + inline void SerializationOp(Stream& s, Operation ser_action) { - READWRITE(this->nVersion); + READWRITE(nVersion); READWRITE(nCreateTime); if (HasKeyOrigin()) { READWRITE(hd_seed_id); diff --git a/src/zazr/deterministicmint.h b/src/zazr/deterministicmint.h index a0ffef7a1..c12a6253f 100644 --- a/src/zazr/deterministicmint.h +++ b/src/zazr/deterministicmint.h @@ -49,9 +49,9 @@ class CDeterministicMint ADD_SERIALIZE_METHODS; template - inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) + inline void SerializationOp(Stream& s, Operation ser_action) { - READWRITE(this->nVersion); + READWRITE(nVersion); READWRITE(nCount); READWRITE(hashSeed); READWRITE(hashSerial); diff --git a/src/zazr/zazrmodule.h b/src/zazr/zazrmodule.h index 5ad26cd78..69a7c4625 100644 --- a/src/zazr/zazrmodule.h +++ b/src/zazr/zazrmodule.h @@ -54,7 +54,8 @@ class PublicCoinSpend : public libzerocoin::CoinSpend { ADD_SERIALIZE_METHODS; template - inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { + inline void SerializationOp(Stream& s, Operation ser_action) { + READWRITE(version); if (version < PUBSPEND_SCHNORR) { diff --git a/src/zazr/zazrwallet.cpp b/src/zazr/zazrwallet.cpp index 3420394bb..0da65117a 100644 --- a/src/zazr/zazrwallet.cpp +++ b/src/zazr/zazrwallet.cpp @@ -327,7 +327,7 @@ bool CzAZRWallet::SetMintSeen(const CBigNum& bnValue, const int& nHeight, const wallet->AddToWallet(wtx, false, &walletdb); } - // Add to zpivTracker which also adds to database + // Add to zazrTracker which also adds to database wallet->zazrTracker->Add(dMint, true); //Update the count if it is less than the mint's count diff --git a/src/zazr/zerocoin.h b/src/zazr/zerocoin.h index 1c530a6f1..a2623c529 100644 --- a/src/zazr/zerocoin.h +++ b/src/zazr/zerocoin.h @@ -155,7 +155,7 @@ class CZerocoinMint ADD_SERIALIZE_METHODS; template - inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { + inline void SerializationOp(Stream& s, Operation ser_action) { READWRITE(isUsed); READWRITE(randomness); READWRITE(serialNumber); @@ -227,7 +227,7 @@ class CZerocoinSpend ADD_SERIALIZE_METHODS; template - inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { + inline void SerializationOp(Stream& s, Operation ser_action) { READWRITE(coinSerial); READWRITE(hashTx); READWRITE(pubCoin);