Giter Club home page Giter Club logo

qtumproject / qtum Goto Github PK

View Code? Open in Web Editor NEW
1.2K 187.0 398.0 202.99 MB

Qtum Core Wallet

Home Page: https://qtum.org

License: MIT License

Makefile 0.78% Shell 2.72% M4 1.01% QMake 0.01% Python 15.96% C++ 70.72% C 6.88% HTML 0.09% Objective-C++ 0.02% Assembly 0.55% Java 0.01% Batchfile 0.02% Perl 0.01% CMake 0.43% CSS 0.45% Scheme 0.10% Sage 0.24% Cap'n Proto 0.01% Dockerfile 0.01%
cryptocurrency cryptography c-plus-plus p2p ethereum bitcoin qtum

qtum's Introduction

What is Qtum?

Qtum is a decentralized blockchain project built on Bitcoin's UTXO model, with support for Ethereum Virtual Machine based smart contracts, and secured by a proof of stake consensus model. It achieves this through the revolutionary Account Abstraction Layer which allows the EVM to communicate with Qtum's Bitcoin-like UTXO blockchain. For more general information about Qtum as well as links to join our community, go to https://qtum.org

Welcome to the Qtum Fastlane Main Network. This is the main network where the tokens hold value and should be guarded very carefully. If you are testing the network, or developing unstable software on Qtum, we highly recommend using either testnet or regtest mode.

The major features of the Qtum network include:

  1. Compatibility with the Ethereum Virtual Machine, which allows for compatibility with most existing Solidity based smart contracts. No special solidity compiler is required to deploy your smart contract to Qtum.
  2. A Proof of Stake consensus system which is optimized for Qtum's contract model. Any user can stake and help to secure the network. There is no voting, master nodes, or minimum amount required. There have been transactions as small as 2 Qtum that have created blocks in the past. Staking from smart contracts is under development.
  3. The Decentralized Governance Protocol is completely implemented and functional, which allows certain network parameters to be modified without a fork or other network disruption. This currently controls parameters like block size, gas prices, etc.
  4. Uses the UTXO transaction model and is compatible with Bitcoin, allowing for existing tooling and workflows to be used with Qtum. This allows for the infamous SPV protocol to be used which is ideal for light wallets on mobile phones and IoT devices.

Note: Qtum Core is considered beta software. We make no warranties or guarantees of its security or stability.

Qtum Documentation and Usage Resources

These are some resources that might be helpful in understanding Qtum.

Basic usage resources:

Development resources:

General Info about Qtum:

Developer's Tools

What is Qtum Core?

Qtum Core is our primary mainnet wallet. It implements a full node and is capable of storing, validating, and distributing all history of the Qtum network. Qtum Core is considered the reference implementation for the Qtum network.

Qtum Core currently implements the following:

  • Sending/Receiving QTUM coins
  • Sending/Receiving QRC20 tokens on the Qtum network
  • Staking and creating blocks for the Qtum network
  • Creating and interacting with smart contracts
  • Running a full node for distributing the blockchain to other users
  • "Prune" mode, which minimizes disk usage
  • Regtest mode, which enables developers to very quickly build their own private Qtum network for Dapp testing
  • Testnet mode, using the public Qtum Testnet, with faucet available
  • Compatibility with the Bitcoin Core set of RPC commands and APIs
  • Full SegWit capability with p2sh-segwit (legacy) and bech32 (native) addresses

Alternative Wallets

Qtum Core uses a full node model, and thus requires downloading the entire blockchain. If you do not need the entire blockchain, and do not intend on developing smart contracts, it may be more ideal to use an alternative wallet such as one of our light wallets that can be synchronized in a matter of seconds.

Qtum Web Wallet

A browser wallet that supports the Ledger hardware wallet, offline cold wallet, restoration from mobile wallets, creation of QRC20 tokens and QRC1155 NFTs.

Web site https://qtumwallet.org

User documentation https://github.com/qtumproject/documents/tree/master/en/QTUM-WebWallet-usage

Qtum Electrum

A light wallet that supports the Ledger and Trezor hardware wallets and is based on the well-known Electrum wallet software.

Download: https://github.com/qtumproject/qtum-electrum/releases

iOS and Android Wallets

These wallets run on mobile devices and synchronize quickly.

Android Download: https://play.google.com/store/apps/details?id=org.qtum.newwallet

iOS Download: https://github.com/qtumproject/qtum-ios (open source, deprecated)

Qnekt Chrome Wallet

This light wallet runs in your Chrome browser as a browser extension, based on the popular MetaMask wallet.

Community Resources

Make sure to check out these resources as well for more information and to keep up to date with all the latest news about Qtum. At least 1 developer is always around, so if you're developing on Qtum and need help, we'd love to welcome you to our community.

Qtum Smart Contract Limitations

  • EVM smart contracts cannot receive coins from or send coins to any address type other than pay-to-pubkeyhash (starts with Q) addresses. This is due to a limitation in the EVM
  • Contracts are not allowed to create contracts with an initial endowment of coins. The contract must first be created, and then be sent coins in a separate transaction. Humans are also not allowed to create contracts with an initial endowment of coins.
  • Although all of the infrastructure is present, Qtum Core does not currently parse Solidity event data. You must parse this yourself using either searchlogs or -record-log-opcodes features.
  • It is not possible to send a contract coins without also executing the contract. This is also the case of Ethereum. This was promised in earlier discussions and technically does work, but due to lack of time for testing this feature was disabled.
  • In Qtum there can be multiple addresses used to create a proof-of-stake block. However, the EVM can only see the first output using the coinbase operation in Solidity (this address is also the one registered for the continuous staker rewards after 2000 blocks).

Building Qtum Core

Validate and Reproduce Binaries

Qtum uses a tool called Gitian to make reproducible builds that can be verified by anyone. Instructions on setting up a Gitian VM and building Qtum are provided in Gitan Building

Build on Ubuntu

This is a quick start script for compiling Qtum on Ubuntu

    sudo apt-get install build-essential libtool autotools-dev automake pkg-config libssl-dev libevent-dev bsdmainutils git cmake libboost-all-dev libgmp3-dev bison libtool-bin
    sudo apt-get install software-properties-common
    
    # If you want to build the Qt GUI:
    sudo apt-get install libqt5gui5 libqt5core5a libqt5dbus5 qttools5-dev qttools5-dev-tools libprotobuf-dev protobuf-compiler qrencode
    
    git clone https://github.com/qtumproject/qtum
    cd qtum
    git submodule update --init --recursive

    ./contrib/install_db4.sh `pwd`
    export BDB_PREFIX='/path/to/qtum/db4'

    cd depends
    make

    # replace x86_64-pc-linux-gnu with the appropriate folder name for your system
    libtool --finish depends/x86_64-pc-linux-gnu/lib 
    export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:`pwd`/x86_64-pc-linux-gnu/lib
    
    # Note: autogen will prompt to install some more dependencies if needed
    ./contrib/install_db4.sh `pwd`
    ./autogen.sh
    ./configure --prefix=`pwd`/depends/x86_64-pc-linux-gnu
    make -j$(nproc)

Build on CentOS

Here is a brief description for compiling Qtum on CentOS, for more details please refer to the specific document

# Compiling boost manually
sudo yum install python-devel bzip2-devel
git clone https://github.com/boostorg/boost.git
cd boost
git checkout boost-1.66.0
git submodule update --init --recursive
./bootstrap.sh --prefix=/usr --libdir=/usr/lib64
./b2 headers
sudo ./b2 -j4 install

# Installing Dependencies for Qtum
sudo yum install epel-release
sudo yum install libtool libdb4-cxx-devel openssl-devel libevent-devel gmp-devel

# If you want to build the Qt GUI:
sudo yum install qt5-qttools-devel protobuf-devel qrencode-devel

# Building Qtum
git clone --recursive https://github.com/qtumproject/qtum.git
cd qtum
./autogen.sh
./configure
make -j4

Build on Mac OS

The commands in this guide should be executed in a Terminal application. The built-in one is located in /Applications/Utilities/Terminal.app.

Preparation

Install the Mac OS command line tools:

xcode-select --install

When the popup appears, click Install.

Then install Homebrew.

Dependencies

brew install cmake automake berkeley-db@4 libtool boost miniupnpc openssl pkg-config protobuf qt@5 libevent imagemagick librsvg qrencode gmp

NOTE: This will work for building on Intel Macs and Apple Silicon Macs

NOTE: Building with Qt4 is still supported, however, could result in a broken UI. Building with Qt5 is recommended.

Build Qtum Core

  1. Clone the qtum source code and cd into qtum

     git clone --recursive https://github.com/qtumproject/qtum.git
     cd qtum
    
  2. Build qtum-core:

    Configure and build the headless qtum binaries as well as the GUI (if Qt is found).

    You can disable the GUI build by passing --without-gui to configure.

    ./autogen.sh
    ./configure
    make
    
  3. It is recommended to build and run the unit tests:

    make check
    

Run

Then you can either run the command-line daemon using src/qtumd and src/qtum-cli, or you can run the Qt GUI using src/qt/qtum-qt

License

Qtum is GPLv3 licensed.

Development Process

The master branch is regularly built and tested, but is not guaranteed to be completely stable. Tags are created regularly to indicate new official, stable release versions of Qtum.

The contribution workflow is described in CONTRIBUTING.md and useful hints for developers can be found in doc/developer-notes.md.

Testing

Testing and code review is the bottleneck for development; we get more pull requests than we can review and test on short notice. Please be patient and help out by testing other people's pull requests, and remember this is a security-critical project where any mistake might cost people lots of money.

Automated Testing

Developers are strongly encouraged to write unit tests for new code, and to submit new unit tests for old code. Unit tests can be compiled and run (assuming they weren't disabled in configure) with: make check. Further details on running and extending unit tests can be found in /src/test/README.md.

There are also regression and integration tests, written in Python. These tests can be run (if the test dependencies are installed) with: test/functional/test_runner.py

The CI (Continuous Integration) systems make sure that every pull request is built for Windows, Linux, and macOS, and that unit/sanity tests are run automatically.

Manual Quality Assurance (QA) Testing

Changes should be tested by somebody other than the developer who wrote the code. This is especially important for large or high-risk changes. It is useful to add a test plan to the pull request description if testing the changes is not straightforward.

Translations

Changes to translations as well as new translations can be submitted to Bitcoin Core's Transifex page.

Translations are periodically pulled from Transifex and merged into the git repository. See the translation process for details on how this works.

Important: We do not accept translation changes as GitHub pull requests because the next pull from Transifex would automatically overwrite them again.

qtum's People

Contributors

achow101 avatar ajtowns avatar dongcarl avatar earlz avatar fanquake avatar gavinandresen avatar glozow avatar gmaxwell avatar hebasto avatar instagibbs avatar jamesob avatar jnewbery avatar jonasschnelli avatar jonatack avatar laanwj avatar luke-jr avatar meshcollider avatar morcos avatar non-github-bitcoin avatar practicalswift avatar promag avatar ryanofsky avatar sdaftuar avatar sipa avatar sjors avatar thebluematt avatar thestack avatar theuni avatar toniqtum avatar vasild avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

qtum's Issues

Tx failing due to absurdly high fees

Txs failing due to high fees. I suspect this issue is related to the changes in #49 since the issue seems to have started appearing after that merge.

Steps to reproduce:

  1. Start qtumd: ./qtumd -regtest
  2. Mine a couple of blocks: ./qtum-cli -regtest generate 16
  3. Create a new account and store an address to it: ADDR=`./qtum-cli -regtest getaccountaddress a`
  4. Send 1 qtum to the account's address: ./qtum-cli -regtest sendfrom "" $ADDR 1.0
  5. Mine this tx: ./qtum-cli -regtest generate 1
  6. Send 1.0 qtum from the account to a random address: ./qtum-cli -regtest sendfrom a qabmqZk3re5b9UpUcznxDkCnCsnKdmPktT 1.0
  7. Check the mempool: ./qtum-cli -regtest getrawmempool

Expected results:

The mempool contains 1 tx

Actual results:

The last tx is is rejected. In the debug.log the below is found:
CommitTransaction(): Transaction cannot be broadcast immediately, absurdly-high-fee

When a gas refund is received it appears as a "stake" balance

Use ./qtum-cli reservebalance true 100000000 to reserve all balance (this prevents staking), then try creating a contract. When a block is created, the gas refund shows up as part of the "stake" balance. Maybe we should change this to be "immature" ?

Unclean shutdown of qtumd

The error below shows up when using rpc stop command or ctrl+c:

libc++abi.dylib: terminating with uncaught exception of type std::__1::system_error: mutex lock failed: Invalid argument Abort trap: 6

Machine specs:

  • OS: OSX 10.12.3

Reindex causes segfault

Description

Mining a block, stopping qtumd then restarting qtumd with -reindex causes a segfault:

Steps to reproduce

  1. Start a clean qtumd instance in regtest mode: ./qtumd -regtest
  2. Mine a few blocks: ./qtum-cli -regtest generate 1
  3. Stop qtumd
  4. Restart qtumd with reindex set: ./qtumd -regtest -reindex

Expected behaviour

  1. The block height is 1

Actual behaviour

qtumd segfaults

OSX: Contracts not saved in the state

After the last 2 PRs merge, it seems contracts are not saved in the state:

In OSX:

  1. createcontract 6060604052341561000c57fe5b5b6101eb8061001c6000396000f30060606040526000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063561a57b214610046578063b60d428814610058575bfe5b341561004e57fe5b610056610062565b005b61006061016b565b005b600060008054806001018281610078919061016e565b916000526020600020900160005b33909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050600090505b600080549050811015610167576000818154811015156100e957fe5b906000526020600020900160005b9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc6305f5e1009081150290604051809050600060405180830381858888f19350505050151561015957fe5b5b80806001019150506100cd565b5b50565b5b565b81548183558181151161019557818360005260206000209182019101610194919061019a565b5b505050565b6101bc91905b808211156101b85760008160009055506001016101a0565b5090565b905600a165627a7a72305820ebde37344a0749ed3bea82ffe57c25c0c4fcb3ec8842d7393482ecc8938e7b6a0029 10000000 0.001

  2. mine a block

  3. listcontracts returns an empty state

debug.log shows ERROR: ConnectBlock(): Incorrect transactions or hashes(hashStateRoot, hashUTXORoot).

Silent out of gas exception

There is a case where an out of gas exception occurs, but the vm or debug logs does not report anything.

createcontract 6060604052341561000c57fe5b5b6101eb8061001c6000396000f30060606040526000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063561a57b214610046578063b60d428814610058575bfe5b341561004e57fe5b610056610062565b005b61006061016b565b005b600060008054806001018281610078919061016e565b916000526020600020900160005b33909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050600090505b600080549050811015610167576000818154811015156100e957fe5b906000526020600020900160005b9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc6305f5e1009081150290604051809050600060405180830381858888f19350505050151561015957fe5b5b80806001019150506100cd565b5b50565b5b565b81548183558181151161019557818360005260206000209182019101610194919061019a565b5b505050565b6101bc91905b808211156101b85760008160009055506001016101a0565b5090565b905600a165627a7a72305820ebde37344a0749ed3bea82ffe57c25c0c4fcb3ec8842d7393482ecc8938e7b6a0029 100000 0.0000001
  1. mine a block

  2. the contract is not created, and the miner gets all gas, but no trace of the exception in any of the logs.

osx: test_qtum binary crashes at launch

This issue appeared after merging PR: #56

Tests fail on OSX:

libc++abi.dylib: terminating with uncaught exception of type boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<boost::lock_error> >: boost: mutex lock failed in pthread_mutex_lock: Invalid argument Abort trap: 6

OS: Sierra 10.12.4

Blocks generated after segwit activation fail when containing txs.

After mining 431 blocks and thereby activating segwit, blocks generated thereafter containing txs are invalid.

Steps to reproduce

  1. Start qtumd: ./qtumd -regtest
  2. Mine 431 blocks: ./qtum-cli -regtest generate 431
  3. Send some qtum to an address: ./qtum-cli -regtest sendtoaddress qabmqZk3re5b9UpUcznxDkCnCsnKdmPktT 0.1
  4. Mine a new block: ./qtum-cli -regtest generate 1

Expected results

  1. No errors.
  2. Block height is 432.

Actual results

The call to generate fails with the error
CreateNewBlock: TestBlockValidity failed: bad-witness-merkle-match, ContextualCheckBlock : witness merkle commitment mismatch (code 16)

Default gas stipend in sendtocontract and createcontract too low.

Description

After the update in #146 the default gas stipend (10000 gas) in createcontract and sendtocontract is too low to create or send to contracts.

Steps to reproduce

  1. Start qtumd: ./qtumd -regtest
  2. Mine some blocks: ./qtum-cli -regtest generate 20
  3. Create a contract: ./qtum-cli -regtest createcontract "00"
  4. Mine this contract: ./qtum-cli -regtest generate 1
  5. List contracts: ./qtum-cli -regtest listcontracts

Expected results:

  1. The default gas stipend should have been enough to create an empty contract

Actual results:

  1. No contract is created since 10000 gas is too little to create the contract.

Signedness problem in gas limit/gas price.

Describe the issue

When executing an op create or call with a gas limit/price that could be interpreted as a negative integer the tx is accepted but contract creation/call fails due to the gas supplied exceeds the block gas limit. This appears to be the same as the old signedness issue.

Steps to reproduce

  1. Start qtumd
  2. Send a tx with one output with the example scriptPubKey below (a scriptPubKey with a gas limit of 0xffff)
  3. Mine this tx

Expected behavior

The tx should either be rejected due to having a negative gas value or it should consistently be treated as an unsigned integer.

Actual behaviour

The contract creation/call fails on generate

Example of output:

Cannot fit tx in block 31 : Require < 500000000 Got 115792089237316195423570985008687907853269984665640564039457584007913096872936

ScriptPubKey

5d010102ffff02e8034c5260606040523415600b57fe5b5b60398060196000396000f30060606040525b600b5b5b565b0000a165627a7a7230582092926a9814888ff08700cbd86cf4ff8c50052f5fd894e794570d9551733591d60029c1

Full example tx

020000000158f7c43c7adeaaece4e344175622c2ed55a5938bd1440f9b4cf5943420df75750100000000000000000100000000000000005d010102ffff02e8034c5260606040523415600b57fe5b5b60398060196000396000f30060606040525b600b5b5b565b0000a165627a7a7230582092926a9814888ff08700cbd86cf4ff8c50052f5fd894e794570d9551733591d60029c100000000

OP_CALL to address 0x0 results in contract creation.

Description

Making an OP_CALL output to address 0x0000000000000000000000000000000000000000 results in it being treated as an OP_CREATE when executed and creates a new contract.
The test below sends a tx with an output where the scriptPubKey is 1 100000 1 0 0000000000000000000000000000000000000000 OP_CALL.

Steps to reproduce:

  1. Checkout the djaen/python-qa-op-call-top-null branch
  2. Run the test from the qtum root folder: BITCOIND=qtumd qa/rpc-tests/qtum-op-call-to-null.py

Expected result:

  1. The test should not fail (The test sends a tx containing the output above and checks that there exists no new contracts).

Actual result:

  1. A new contract is created and therefore the test fails.

Possible to set nValue of second coinbase output to non-zero value in PoS blocks.

Description

It is possible to set the nValue of the coinbase vout created by GenerateCoinbaseCommitment to > 0 in PoS blocks (the second output of the coinbase). Since this output is effectively a burn output (the scriptPubKey begins with an OP_RETURN) the coins created are unspendable. But since it enables coin creation out of thin air, even though they are immediately burned, it may anyways be good to add a check for it.

Steps to reproduce

Start 2 nodes A and B. A is a malicious node that has been modified with the diff file below. B is a clean node. This test was performed on mainnet after generating all PoW blocks on A.

  1. Wait for A to generate a PoS block.
  2. Check if the block created by A has been accepted by B.

Expected results:

  1. The block is rejected due to the coinbase having a non-zero output in a PoS block.

Actual results:

  1. The block is accepted.

Malicious node diff:

diff --git a/src/validation.cpp b/src/validation.cpp
index 63421c1..a52bea8 100644
--- a/src/validation.cpp
+++ b/src/validation.cpp
@@ -3637,7 +3637,7 @@ std::vector<unsigned char> GenerateCoinbaseCommitment(CBlock& block, const CBloc
             uint256 witnessroot = BlockWitnessMerkleRoot(block, NULL, &fProofOfStake);
             CHash256().Write(witnessroot.begin(), 32).Write(&ret[0], 32).Finalize(witnessroot.begin());
             CTxOut out;
-            out.nValue = 0;
+            out.nValue = 1000000000000;
             out.scriptPubKey.resize(38);
             out.scriptPubKey[0] = OP_RETURN;
             out.scriptPubKey[1] = 0x24;

segfault on decodescript

Qtumd segfaults when calling decodescript prefixed with OP_0.

  1. Start qtumd in regtest mode: ./qtumd -regtest
  2. Call decodescript with OP_0 as arg: ./qtum-cli -regtest decodescript 00

Expected results:

  1. Decodes the script

Actual results:

  1. Segfault

Error synchronizing node.

Description

When synchronizing a node with the flag -gen = 1, we get:
qtumd: miner.cpp:932: void QtumMiner(const CChainParams&): Assertion `hash == pblock->GetHash()' failed.

Steps to reproduce

  1. Start node 1 (-gen=1).
  2. Start node 2 (-gen=1).
  3. Connect to node from node 1.

Expected result

Nodes are synchronized.

Actual result

qtumd: miner.cpp:932: void QtumMiner(const CChainParams&): Assertion `hash == pblock->GetHash()' failed.

Gas refunds appear to not be correctly issued when the number of txs that include op_call or op_create > 1.

Description

When the number of evm txs exceed 1 the gas refunds in the coinbase are all (except for 1) assigned to the miner.

Steps to reproduce

  1. Start qtumd in regtest mode: ./qtumd -regtest
  2. Mine some blocks: ./qtum-cli -regtest generate 20
  3. Create 40 very simple contracts, set the gas limit to 0.1 qtum and the gas price to the lowest possible value (0.00000001): for i in {0..40}; do ./qtum-cli -regtest createcontract 6060604052341561000c57fe5b5b60ab8061001b6000396000f30060606040523615603d576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806361bc221a146056575b60545b60016000600082825401925050819055505b565b005b3415605d57fe5b60636079565b6040518082815260200191505060405180910390f35b600054815600a165627a7a72305820e0099ccfa19f86fb5d2e77ef5c38653aa5cb9226977f9f37d31e43cbd5cf6a680029 10000000 0.00000001; done
  4. Mine these txs: ./qtum-cli -regtest generate 1
  5. Verify that the 40 contracts were created successfully ./qtum-cli -regtest listcontracts 1 40
  6. Get the coinbase tx: ./qtum-cli -regtest getrawtransaction $(./qtum-cli -regtest getblock $(./qtum-cli -regtest getbestblockhash) | python3 -c "import sys; import json; print(json.loads(sys.stdin.read())['tx'][0])")

Expected results:

  1. There are 40 gas refund outputs in the coinbase that are gas refunds of ~0.1 qtum

Actual results:

  1. There is only one gas refund, the rest of the gas refunds assigned to the miner.

Mining several txs resulting in large evm tx results in invalid block

Description

A contract that, when called, creates a large evm tx, result in an invalid block when several txs calling that contract are mined.

Steps to reproduce

  1. Start qtumd in regtest mode: ./qtumd -regtest
  2. Mine some blocks: ./qtum-cli -regtest generate 20
  3. Create a contract and store its address (source below): CONTRACT=$(./qtum-cli -regtest createcontract 6060604052341561000c57fe5b5b60b28061001b6000396000f30060606040525b60845b6000600090505b620186a05a11156080578073ffffffffffffffffffffffffffffffffffffffff166108fc6127103073ffffffffffffffffffffffffffffffffffffffff1631811515605657fe5b049081150290604051809050600060405180830381858888f19350505050505b806001019050600f565b5b50565b0000a165627a7a723058203e394ff6da708a4052dffc2b99c0e76da026ec47919d635090d456b1595138090029 | python3 -c "import json; import sys; print(json.loads(sys.stdin.read())['address'])")
  4. Mine this contract: ./qtum-cli -regtest generate 1
  5. Send a tx that will call the default function with a large gas stipend: ./qtum-cli -regtest sendtocontract $CONTRACT 00 1 500000000 0.00000001
  6. Send another identical tx: ./qtum-cli -regtest sendtocontract $CONTRACT 00 1 500000000 0.00000001
  7. Mine these txs: ./qtum-cli -regtest generate 1

Expected results:

  1. A block is mined.

Actual results:

  1. CreateNewBlock: TestBlockValidity failed: bad-blk-sigops, out-of-bounds SigOpCount (code 16)

Contract source:

pragma solidity ^0.4.11;

contract Manyp2pkhOutputs {
    function() payable {
        for(uint i = 0; msg.gas > 100000; ++i) {
            address(i).send(this.balance / 10000);
        }
    }
}

BIP34 scriptSig error at block 1 due to activation from genesis.

Update

I have updated the issue, since I this issue only seems to apply to the first block, i.e. setting the activation from block 1 instead of 0 the issue disappears.

Description

When a block is serialized and then deserialized (either by writing it to then reading it from disk or transferring it over the network) the BIP34 scriptSig check fails.

To reproduce the issue

Prerequisites: A clean qtum chain.

  1. Start qtumd: ./qtumd
  2. Mine a block: ./qtum-cli generate 1
  3. Close qtumd
  4. reindex the block: ./qtumd -reindex

Expected behaviour

qtumd starts as normal and successfully reindexes the block.

Actual behaviour

  • qtumd becomes unresponsive.
  • debug.log states: ERROR: AcceptBlock: bad-cb-height, block height mismatch in coinbase (code 16)

References:

debug.log

2017-04-03 12:18:26 mapAddressBook.size() = 1
2017-04-03 12:18:26 Reindexing block file blk00000.dat...
2017-04-03 12:18:26 ERROR: AcceptBlock: bad-cb-height, block height mismatch in coinbase (code 16)
2017-04-03 12:18:26 ERROR: AcceptBlockHeader: prev block invalid
2017-04-03 12:18:26 Reindexing finished
2017-04-03 12:18:26 Initializing databases...
2017-04-03 12:18:26 Pre-allocating up to position 0x1000000 in blk00000.dat
2017-04-03 12:18:26 Imported mempool transactions from disk: 0 successes, 0 failed, 0 expired

Compilation warning

validation.cpp: In function โ€˜bool CheckBlock(const CBlock&, CValidationState&, const Consensus::Params&, bool, bool, bool)โ€™:
validation.cpp:3560:13: warning: unused variable โ€˜commitposโ€™ [-Wunused-variable] int commitpos = GetWitnessCommitmentIndex(block);

Combination of OP_SPEND and OP_CREATE in a scriptPubKey causes qtumd to crash

Description

Inserting an OP_SPEND in a OP_CREATE scriptPubKey causes qtumd to either run out of memory or simply crash in some cases. An example of such a scriptPubKey is: 1 OP_SPEND OP_CREATE. The test below sends a tx with such an output using sendrawtransaction which causes qtumd to crash.

Steps to reproduce

  1. Checkout the djaen/python-qa-scriptpubkey-test branch.
  2. Run the test: BITCOIND=qtumd qa/rpc-tests/qtum-scriptpubkey.py

Note: the error varies, sometimes no error is visible in the debug.log.

debug.log

2017-06-20 21:33:35 Error: Out of memory. Terminating.

debug info

#0  0x00007ffff521d428 in __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:54
#1  0x00007ffff521f02a in __GI_abort () at abort.c:89
#2  0x00007ffff5d7d84d in __gnu_cxx::__verbose_terminate_handler() ()
   from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#3  0x00007ffff5d7b6b6 in ?? () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#4  0x00007ffff5d7b701 in std::terminate() () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#5  0x000055555564dd05 in new_handler_terminate () at init.cpp:819
#6  0x00007ffff5d7be8c in operator new(unsigned long) () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#7  0x000055555572f0c0 in __gnu_cxx::new_allocator<unsigned char>::allocate (this=0x7fffe2ffa0e0, 
    __n=<optimized out>) at /usr/include/c++/5/ext/new_allocator.h:104
#8  std::allocator_traits<std::allocator<unsigned char> >::allocate (__a=..., __n=<optimized out>)
    at /usr/include/c++/5/bits/alloc_traits.h:491
#9  std::_Vector_base<unsigned char, std::allocator<unsigned char> >::_M_allocate (
    this=0x7fffe2ffa0e0, __n=<optimized out>) at /usr/include/c++/5/bits/stl_vector.h:170
#10 std::_Vector_base<unsigned char, std::allocator<unsigned char> >::_M_create_storage (
    __n=<optimized out>, this=0x7fffe2ffa0e0) at /usr/include/c++/5/bits/stl_vector.h:185
#11 std::_Vector_base<unsigned char, std::allocator<unsigned char> >::_Vector_base (__a=..., 
    __n=<optimized out>, this=0x7fffe2ffa0e0) at /usr/include/c++/5/bits/stl_vector.h:136
#12 std::vector<unsigned char, std::allocator<unsigned char> >::vector (this=0x7fffe2ffa0e0, 
    __x=std::vector of length -7598807741480432387, capacity -7598807741480460621 = {...})
    at /usr/include/c++/5/bits/stl_vector.h:320
#13 0x00005555557b1ea2 in QtumTxConverter::parseEthTXParams (this=this@entry=0x7fffe2ffb5d0)
    at validation.cpp:2165
#14 0x00005555557c1945 in QtumTxConverter::extractionQtumTransactions (this=this@entry=0x7fffe2ffb5d0)
    at validation.cpp:2128
#15 0x00005555557cf3b4 in AcceptToMemoryPoolWorker (pool=..., state=..., 
---Type <return> to continue, or q <return> to quit---
    ptx=std::shared_ptr (count 1, weak 0) 0x7fffb00010c0, fLimitFree=fLimitFree@entry=false, 
    pfMissingInputs=pfMissingInputs@entry=0x7fffe2ffbb80, nAcceptTime=1497994415, plTxnReplaced=0x0, 
    fOverrideMempoolLimit=false, nAbsurdFee=@0x7fffe2ffb958: 10000000, 
    vHashTxnToUncache=std::vector of length 1, capacity 1 = {...}) at validation.cpp:762
#16 0x00005555557d2b6b in AcceptToMemoryPoolWithTime (pool=..., state=..., 
    tx=std::shared_ptr (count 1, weak 0) 0x7fffb00010c0, fLimitFree=fLimitFree@entry=false, 
    pfMissingInputs=pfMissingInputs@entry=0x7fffe2ffbb80, nAcceptTime=<optimized out>, 
    plTxnReplaced=0x0, fOverrideMempoolLimit=false, nAbsurdFee=10000000) at validation.cpp:1092
#17 0x00005555557d2cd9 in AcceptToMemoryPool (pool=..., state=..., 
    tx=std::shared_ptr (count 1, weak 0) 0x7fffb00010c0, fLimitFree=fLimitFree@entry=false, 
    pfMissingInputs=pfMissingInputs@entry=0x7fffe2ffbb80, plTxnReplaced=plTxnReplaced@entry=0x0, 
    fOverrideMempoolLimit=false, nAbsurdFee=10000000) at validation.cpp:1121
#18 0x00005555557570cf in sendrawtransaction (request=...) at rpc/rawtransaction.cpp:907

Suicides to non-existant address create a contract in the state.

Description

A suicide with an argument to a non-existant address creates a new account at that address in the state. This seems like unintended behaviour according to our model.

Steps to reproduce

  1. Start qtumd in regtest mode: ./qtumd -regtest
  2. Mine some blocks: ./qtum-cli -regtest generate 20
  3. Create a new contract that suicides and refunds the contract's balance to the address at 0xe0e on calling the fallback function, store the contract's address for later use CONTRACT=$(./qtum-cli -regtest createcontract "60606040523415600b57fe5b5b603d8060196000396000f30060606040525b600f5b610e0eff5b565b0000a165627a7a723058209e90cd77b49430d225c3ebd97a7eabf1282254a9d0260e71448f338a40207fa10029" | python3 -c "import json; import sys; print(json.loads(sys.stdin.read())['address'])")
  4. Mine this tx: ./qtum-cli -regtest generate 1
  5. Send a tx that calls the fallback function: ./qtum-cli -regtest sendtocontract $CONTRACT "00"
  6. Mine this tx: ./qtum-cli -regtest generate 1
  7. List the contracts that currently exists: ./qtum-cli -regtest listcontracts

Expected results:

  1. No contracts should exists.

Actual results:

  1. A contract exists

Suicide contract:

pragma solidity ^0.4.11;

contract Test {
    function () payable {
        suicide(0xe0e);
    }
}

Block generation of PoW blocks fail when generating many blocks in the same rpc call.

Description:

Block generation of PoW blocks fail when generating many blocks in the same rpc call.

Steps to reproduce:

  1. Start qtumd in regtest mode: ./qtumd -regtest
  2. Mine some blocks: ./qtum-cli -regtest generate 100

Expected results:

  1. 100 blocks are created

Actual results:

  1. CreateNewBlock: TestBlockValidity failed: time-too-new, block timestamp too far in the future (code 16)

generate 100 results in ProcessNewBlock, block not accepted

I mined a single block, then after several minutes did generate 100 to mine more. It successfully mined 2 additional blocks, but then at the 3rd block encountered the following error:

2017-05-26 18:47:28 ERROR: AcceptBlock() : block's timestamp is too early
2017-05-26 18:47:28 ERROR: ProcessNewBlock: AcceptBlock FAILED

Expected result:
Generates multiple blocks without error

Actual result:
Encountered error

Fuller log:

2017-05-26 18:47:27 CreateNewBlock(): total size: 335 block weight: 1340 txs: 0 fees: 0 sigops 400
2017-05-26 18:47:27 UpdateTip: new best=00008c6d4d12487c95de1a8e39bd8656d0c579d045872c9c229d32d9e4f85c66 height=2 version=0x20000000 log2_work=17.584985 tx=3 date='2017-05-26 18:47:27' progress=1.000000 cache=0.0MiB(2tx)
2017-05-26 18:47:27 AddToWallet 02c3acd047e02c583143a0ec1921ca374da925d1dd6a6ae60abebcbbc6fe5d86  new
2017-05-26 18:47:28 keypool keep 3
2017-05-26 18:47:28 CreateNewBlock(): total size: 335 block weight: 1340 txs: 0 fees: 0 sigops 400
2017-05-26 18:47:28 CreateNewBlock(): total size: 335 block weight: 1340 txs: 0 fees: 0 sigops 400
2017-05-26 18:47:28 UpdateTip: new best=00005d3556a4662e11733c631e38ebfd166cf9cd5a9753250f1d72ef985681df height=3 version=0x20000000 log2_work=18.000022 tx=4 date='2017-05-26 18:47:28' progress=1.000000 cache=0.0MiB(3tx)
2017-05-26 18:47:28 AddToWallet 50346ea7d14447dcacd16719c8b2438580a4cb172c326fba3c969828b44fa3a0  new
2017-05-26 18:47:28 CreateNewBlock(): total size: 335 block weight: 1340 txs: 0 fees: 0 sigops 400
2017-05-26 18:47:28 CreateNewBlock(): total size: 335 block weight: 1340 txs: 0 fees: 0 sigops 400
2017-05-26 18:47:28 CreateNewBlock(): total size: 335 block weight: 1340 txs: 0 fees: 0 sigops 400
2017-05-26 18:47:28 ERROR: AcceptBlock() : block's timestamp is too early
2017-05-26 18:47:28 ERROR: ProcessNewBlock: AcceptBlock FAILED

Txs from sendtoaddress and sendtocontract mined in the same block results in an invalid block

Description

Doing a sendtoaddress and a sendtocontract (with value) then mining these in the same block results in CreateNewBlock: TestBlockValidity failed: bad-txns-inputs-missingorspent (code 16)

Steps to reproduce

  1. Start qtumd in regtest mode: ./qtumd -regtest
  2. Mine some blocks: ./qtum-cli -regtest generate 200
  3. Create a contract and store its address for use later: CONTRACT=$(./qtum-cli -regtest createcontract "00" | python3 -c "import json; import sys; print(json.loads(sys.stdin.read())['address'])")
  4. Mine this contract: ./qtum-cli -regtest generate 1
  5. Send some qtum to an address: ./qtum-cli -regtest sendtoaddress $(./qtum-cli -regtest getnewaddress) 10
  6. Send some qtum to the contract: ./qtum-cli -regtest sendtocontract $CONTRACT 00 1
  7. Mine a block: ./qtum-cli -regtest generate 1

Expected results:

  1. A block is successfully mined

Actual results:

  1. Block generation fails with CreateNewBlock: TestBlockValidity failed: bad-txns-inputs-missingorspent (code 16)

Compilation warnings in OSX

In file included from ./validation.h:37:
./qtum/qtumstate.h:119:245: warning: field 'state' will be initialized after field 'deleteAddresses' [-Wreorder]
...const std::vector<TransferInfo>& _transfers, const QtumTransaction& _transaction, std::vector<dev::Address> _deleteAddresses = std::vector<dev::Address>()) : transfers(_transfers), transaction(_transaction), state(_state)...

A miner is able to assign the gas refunds to themselves

Description:

  1. Start qtumd in regtest mode: ./qtumd -regtest
  2. Run generate-chain.sh, this will create the a chain of blocks that is referenced by the subsequent block generate-chain.sh.zip: ./generate-chain.sh
  3. Submit a block that includes one tx with a create op that executes successfully (therefore a gas refund should be issued for 2 qtum - the gas spent creating the contract). However, the block is modified so it ignores the expected gas refund and assigns all gas to the miner: ./qtum-cli -regtest submitblock 00000020d05e015fa922462b0b1d160895f67a0530180ddd6e2899f4cdaa37b1c0cc615648ebf35b98958451e4431eb1734a8e7928338b500cb44a8ade109de4c241aac3dbd12159ffff7f20010000006723e78f065784bee41fff075de5e02726a958609c9acb997b58a8969fd24acb56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42100000000000000000000000000000000000000000000000000000000000000000000ffffffff000000000203000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0401150101ffffffff01c4ff35b5d101000023210383ba64ce045c58aab6844c0f5f8d16747932fa6b3803d45a49f00612aebd0957ac00000000d6d121590300000001d62659fbe628fe63fb51b1fce1ab086b236cf50b1866ce0c09cee224f27319210000000049483045022100d091b0ee058efb5060a1735ab613ab291f0aee7b49cc2f5b063e32cb63898ba202206c2621648b21d3d8b9566fb22587209c1b621f115c52dbf091ca14ae948e2c6501feffffff023c405e9dd10100001976a914e0aa8e37e3cae94dd2166bf5fbf418aa872b053188ac0000000000000000d201010400c2eb0b01014cc66060604052341561000c57fe5b5b60ab8061001b6000396000f30060606040523615603d576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806361bc221a146056575b60545b60016000600082825401925050819055505b565b005b3415605d57fe5b60636079565b6040518082815260200191505060405180910390f35b600054815600a165627a7a72305820e0099ccfa19f86fb5d2e77ef5c38653aa5cb9226977f9f37d31e43cbd5cf6a680029c114000000d6d12159
  4. Display the coinbase of the modified block: ./qtum-cli -regtest getrawtransaction 19d86b2bbd5c66da94cddd5148355a96569d2cf7de3949d94f5c81e6383227a9 true

Expected results:

  1. At step 3 the block should be rejected due to gas refunds not being correctly issued.

Actual results:

  1. The block is accepted.
  2. It is possible for the miner to assign all gas refunds to themselves.

Syncing PoS nodes tries to process headers as PoW when syncing

Reproduce:

  1. Setup mainnet network with 3 nodes
  2. Mine all 5000 PoW blocks
  3. Distribute coins to all 3 nodes
  4. Mine 5000 PoS blocks
  5. Stop a node
  6. Let the network continue running for 1000-2000 blocks
  7. Start the previously stopped node

Expected result:
Previously stopped node successfully syncs with the network and does not try to create an orphan or fork chain

Actual result:
Previously stopped node does not sync and has this in the debug.log:

2017-05-29 15:18:02 receive version message: /Satoshi:0.14.0/: version 70015, blocks=11396, us=XXXX:3888, peer=0
2017-05-29 15:18:02 ERROR: AcceptBlockHeader: Consensus::CheckBlockHeader: eaff38aeb6515324d49427c037daae7311c337305658c0ecea5ad61f05270f3f, high-hash, proof of work failed (code 16)
2017-05-29 15:18:02 Misbehaving: XXXX:59901 peer=0 (0 -> 50)
2017-05-29 15:18:02 ERROR: invalid header received
2017-05-29 15:18:02 ProcessMessages(headers, 107635 bytes) FAILED peer=0

Clients do not sync

After starting a second node, it connects to the network, but does not receive blocks

steps to reproduce below:

  1. Start a node and mine some blocks, create contracts ...
  2. Start a second node
  3. The second node is connected but does not get blocks

Machine specs:

  • OS: OSX Sierra

-reindex fails on PoS blocks

Reproduce:

  1. start 2 nodes
  2. mine some pow blocks (50)
  3. stake 10 blocks
  4. shutdown both nodes
  5. start one node with -reindex

Expected result:
Node syncs up to block 60

Result:
Node syncs up to block 50 and rejects the first PoS block

'2017-06-07 02:00:40 LoadExternalBlockFile: Deserialize or I/O error - Read attempted past buffer limit: unspecified iostream_category error 2017-06-07 02:00:40 ERROR: AcceptBlockHeader: Consensus::CheckBlockHeader: 62848323c81c4e82eb8f5a2a2fb7d60eed12a44c636e1c304e33c07e3d5a679e, kernel-hash, proof of stake failed (code 16)'

Reindex fails

Description

Starting a clean instance of qtumd, generating one block and then restarting with -reindex causes an assertion to fail.

Steps to reproduce

  1. Start qtumd in regtest mode: ./qtumd -regtest
  2. Mine a block: ./qtum-cli -regtest generate 1
  3. Restart qtumd with -reindex: ./qtumd -regtest -reindex

Expected results:

qtumd starts successfully

Actual results:

qtumd: validation.cpp:4771: void CheckBlockIndex(const Consensus::Params&): Assertion `mapBlockIndex.size() <= 1' failed.

Segfault when submitting PoS blocks without a coinstake tx over the network

Description

Qtumd segfaults when a PoS block is received over the network without containing the coinstake tx (the second tx).
The problem this time appears to be in net_processing.cpp when it is calling GetProofOfStake() which in turn does an out of range access.

Steps to reproduce

  1. Checkout the branch with the test case: git checkout djaen/python-qa-pos-tests-1
  2. Run the test case from the qtum root folder: BITCOIND=qtumd qa/rpc-tests/qtum-pos.py

Expected results:

  1. The test case completes successfully within a few seconds, i.e., a block without a coinstake tx is rejected.

Actual results:

  1. The test case never completes due to qtumd crashing. Note: no error message will be displayed, the test will simply just hang.

Header-first syncing can not validate PoS block headers

When syncing a new node it's been observed that the node will fall out of sync, complaining that the proof of stake hash is invalid. This is actually not from the hash being invalid, but rather from it being incapable of fully validating the stake transaction. We need to read the transaction data from the txindex in order to validate the stake transaction. However, when syncing a new node, it first requests/receives all headers for the blockchain, and only afterwards does it begin to fetch block bodies that contain transaction data.

This could be worked around by simply disabling PoS hash checking for headers. However, this could be a potential DoS vector (still being evaluated if this is minor enough to not worry about). We also need to check that full blocks always have PoS stake transaction data available (ie, aren't processed out of order beyond COINBASE_MATURITY)

Possible to submit a block with an arbitrary hashStateRoot or hashUTXORoot.

Description

It is possible to submit a block with an arbitrary hashStateRoot or hashUTXORoot. However, it is not possible to submit both an arbitrary hashStateRoot and hashUTXORoot in the same block.

Steps to reproduce:

  1. Start a clean chain of qtumd in regtest mode: ./qtumd -regtest
  2. Submit a block with an arbitrary hashStateRoot (or a hashUTXORoot), note that the hashStateRoot has been set to 0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa: ./qtum-cli -regtest submitblock 04000000cc275975cf7f037ee834ade9864858572ef6b4c1719a0dd4a2dcc15909a20219452503e6ead46471e50f06748f917c5749be48016ed2c80c68e795c898d14647cc590b59ffff7f2002000000aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42100000000000000000000000000000000000000000000000000000000000000000000ffffffff000000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff03510100ffffffff0100204aa9d1010000015100000000

Expected results:

  1. The block is rejected with a "diverged-state-root" error (as happens when submitting a block with both an invalid hashStateRoot and hashUTXORoot)

Actual results:

  1. The block is accepted.
  2. A call to ./qtum-cli -regtest getblock $(./qtum-cli -regtest getbestblockhash) shows the hashStateRoot (or hashUTXORoot) to be 0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

Staking various issues

First value is staking when calling getstakinginfo is always false even when the staker is working.

Second is difficulty and netstakeweight shows different values in different nodes for the same block while staking.

Third is debug output keeps showing:

2017-06-01 01:56:57 CreateNewBlock(): total size: 321 block weight: 1284 txs: 0 fees: 0 sigops 400
2017-06-01 01:56:57 ERROR: CheckProofOfStake() : INFO: check kernel failed on coinstake 6cce6d458701c4248da156f7ab9d209c0a4f008a582717a4808a6a007615850d, hashProof=d54154a735fcb3ebf6b5b227a34c215b0d645b7add0d90bad258c154ca804a84
2017-06-01 01:56:57 ERROR: CheckStake() : proof-of-stake checking failed

and

2017-06-01 01:06:08 ERROR: AcceptBlock() : block's timestamp is too early
2017-06-01 01:06:08 ERROR: ProcessNewBlock: AcceptBlock FAILED
2017-06-01 01:06:08 ERROR: CheckStake() : ProcessBlock, block not accepted

This is spamming the debug log, and this behaviour cannot be seen in the original PoS implementation. if this output is normal, maybe adding a debug category like qtumd -debug=staking to show it would be better, although it does not seem like a sane behavior, for example the staker should not submit a block if the time is within the drift ...

Fourth is the staker should not start if there are no coins available for staking.

Exceeding the block gas limit should not cause out of gas exceptions

When a transaction causes the block's gas limit to be exceeded it should not result in an out of gas condition for the transaction.

Can you reliably reproduce the issue?

If so, please list the steps to reproduce below:

  1. createcontract [any contract bytecode] 1000000
  2. generate 1

Expected behaviour

A new contract should be created

Actual behaviour

The block gas limit is reached, causing the transaction to have an out of gas condition.

We currently appear to calculate the block's gas limit by summing the reported gas limit of each transaction within the block. Instead, we should calculate it by counting the actual used gas by each transaction and reject the block with a DoS error if the gas used exceeds the block limit.

qtumd exits with `Error opening block database` error

After merging all commits, qtumd exits with Error opening block database error:

: Error opening block database.
Please restart with -reindex or -reindex-chainstate to recover.

and if started with -reindex:

Error: Error opening block database

Condensing transaction tests fail.

make check fails with this error:

test/qtumtests/condensingtransaction_tests.cpp:200: error: in "condensingtransaction_tests/condensingtransactiondeep_tests": check tx.vout[i].nValue == values[i] has failed
test/qtumtests/condensingtransaction_tests.cpp:200: error: in "condensingtransaction_tests/condensingtransactiondeep_tests": check tx.vout[i].nValue == values[i] has failed
test/qtumtests/condensingtransaction_tests.cpp:200: error: in "condensingtransaction_tests/condensingtransactiondeep_tests": check tx.vout[i].nValue == values[i] has failed

After numerous transfers of tokens between account and UTXO Error message appearing (mandatory-script-verify-flag-failed).

Description

After numerous transfers of tokens between account and UTXO Error message appearing
(mandatory-script-verify-flag-failed).

Steps to reproduce

  1. Start qtumd in regtest mode: ./qtumd -regtest.
  2. Mine some blocks: ./qtum-cli -regtest generate 20.
  3. Create a contract twice:
contract Test11{
    function() payable { }
}
  1. Generate block.
  2. Create contract:
contract Test1 {
    address Sender1 = 0xeae2af876e5575e4fc8566b9c910df6ed921eb05; // address contract 1 (step 3)
    address Sender2 = 0xb91479f64111bfe1305760d63c12f02a4f8c9d78; // address contract 2 (step 3)
    address Sender3 = 0xe96887cb042ade101c97c974f4796b4133b947cf;
    
    function transfer() {
        Sender1.send(this.balance/3);
        Sender2.send(this.balance/2);
        Sender3.send(this.balance);
    }
    
    function() payable { }
}
  1. Send tokens to contract from point 5.
  2. Call method transfer.
  3. Send tokens to contract from point 5.
  4. Call method transfer.

Expected results:

  1. Tokens added.

Actual results:

  1. mandatory-script-verify-flag-failed

New nodes fail to sync

This happens 50% of the time, on a clean chain, after mining some PoW and PoS blocks, then starting a new node, the new node fails to sync:

ERROR: AcceptBlockHeader: Consensus::CheckBlockHeader: 7a21f4837a7c4708703fed04f88cb3a36771a959b274cfaec03a7affdb97604b, high-hash, proof of work failed (code 16)

submitblock causes segfault

Note: The block submitted here is an old block which does not include the hashStateRoot

Steps to reproduce

Prerequisites: a clean chain

  1. start qtumd: ./qtumd -regtest
  2. submit a block: ./qtum-cli -regtest submitblock 040000004ce414c7b39ea6094050118df84abf505b2f7fbd08a6c356b41083f20892593f30a95ba00c6a8eda87caf87303faa79d27b8b6b1a9ce2880099b7ac2524e095905d8e358ffff7f20010000000101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff025101ffffffff0100f2052a01000000015100000000

Expected Results

The block is rejected.

Actual results

qtumd segfaults.

Honest nodes segfault when a malicious node sends a PoS block without a coinstake tx.

Description

A malicious node that is modified such that it does not include the coinstake tx in PoS blocks causes the honest nodes of the network to segfault. Note: sometimes the malicious node crashes before relaying the invalid block, so this test may need to be run a couple of times to trigger the behavior.

Steps to reproduce

Start 2 nodes A and B. A is a malicious node that has been modified with the diff file below. B is a clean node.
This test was performed on mainnet after generating all PoW blocks on A.

  1. Wait for A to create PoS block.
  2. Check if the block created by A has been accepted by B.

Expected results:

  1. The block is rejected by B

Actual results:

  1. B segfaults.

Malicious node diff:

diff --git a/src/miner.cpp b/src/miner.cpp
index 4d920fb..4448e47 100644
--- a/src/miner.cpp
+++ b/src/miner.cpp
@@ -712,8 +712,8 @@ bool CheckStake(const std::shared_ptr<const CBlock> pblock, CWallet& wallet)
 
     // verify hash target and signature of coinstake tx
     CValidationState state;
-    if (!CheckProofOfStake(mapBlockIndex[pblock->hashPrevBlock], state, *pblock->vtx[1], pblock->nBits, pblock->nTime, proofHash, hashTarget))
-        return error("CheckStake() : proof-of-stake checking failed");
+    //if (!CheckProofOfStake(mapBlockIndex[pblock->hashPrevBlock], state, *pblock->vtx[1], pblock->nBits, pblock->nTime, proofHash, hashTarget))
+    //    return error("CheckStake() : proof-of-stake checking failed");
 
     //// debug print
     LogPrint("miner", "CheckStake() : new proof-of-stake block found  \n  hash: %s \nproofhash: %s  \ntarget: %s\n", hashBlock.GetHex(), proofHash.GetHex(), hashTarget.GetHex());
diff --git a/src/validation.cpp b/src/validation.cpp
index 63421c1..481bacc 100644
--- a/src/validation.cpp
+++ b/src/validation.cpp
@@ -3414,8 +3414,10 @@ bool SignBlock(std::shared_ptr<CBlock> pblock, CWallet& wallet, const CAmount& n
                 //    as it would be the same as the block timestamp
                 pblock->nTime = nTimeBlock;
                 pblock->vtx[1] = MakeTransactionRef(std::move(txCoinStake));
-                pblock->hashMerkleRoot = BlockMerkleRoot(*pblock);
                 pblock->prevoutStake = pblock->vtx[1]->vin[0].prevout;
+                pblock->vtx.pop_back();
+                pblock->vtx.resize(1);
+                pblock->hashMerkleRoot = BlockMerkleRoot(*pblock);
 
                 // Check timestamp against prev
                 if(pblock->GetBlockTime() <= pindexBestHeader->GetBlockTime() || FutureDrift(pblock->GetBlockTime()) < pindexBestHeader->GetBlockTime())
@@ -3544,21 +3546,21 @@ bool CheckBlock(const CBlock& block, CValidationState& state, const Consensus::P
             return state.DoS(100, false, REJECT_INVALID, "bad-cb-missing", false, "coinbase output not empty for proof-of-stake block");
 
         // Second transaction must be coinstake, the rest must not be
-        if (block.vtx.empty() || !block.vtx[1]->IsCoinStake())
-            return state.DoS(100, false, REJECT_INVALID, "bad-cs-missing", false, "second tx is not coinstake");
+        //if (block.vtx.empty() || !block.vtx[1]->IsCoinStake())
+        //    return state.DoS(100, false, REJECT_INVALID, "bad-cs-missing", false, "second tx is not coinstake");
         for (unsigned int i = 2; i < block.vtx.size(); i++)
             if (block.vtx[i]->IsCoinStake())
                return state.DoS(100, false, REJECT_INVALID, "bad-cs-multiple", false, "more than one coinstake");
 
         //prevoutStake must exactly match the coinstake in the block body
-        if(block.prevoutStake != block.vtx[1]->vin[0].prevout){
-            return state.DoS(100, false, REJECT_INVALID, "bad-cs-invalid", false, "prevoutStake in block header does not match coinstake in block body");
-        }
+        //if(block.prevoutStake != block.vtx[1]->vin[0].prevout){
+        //    return state.DoS(100, false, REJECT_INVALID, "bad-cs-invalid", false, "prevoutStake in block header does not match coinstake in block body");
+        //}
     }
 
     // Check proof-of-stake block signature
-    if (fCheckSig && !CheckBlockSignature(block))
-        return state.DoS(100, false, REJECT_INVALID, "bad-blk-signature", false, "bad proof-of-stake block signature");
+    //if (fCheckSig && !CheckBlockSignature(block))
+    //    return state.DoS(100, false, REJECT_INVALID, "bad-blk-signature", false, "bad proof-of-stake block signature");
 
     // Check transactions
     for (const auto& tx : block.vtx)
@@ -3884,10 +3886,10 @@ static bool AcceptBlock(const std::shared_ptr<const CBlock>& pblock, CValidation
     if (!AcceptBlockHeader(block, state, chainparams, &pindex))
         return false;
 
-    if (!UpdateHashProof(block, state, chainparams.GetConsensus(), pindex))
-    {
-        return error("%s: UpdateHashProof(): %s", __func__, state.GetRejectReason().c_str());
-    }
+    //if (!UpdateHashProof(block, state, chainparams.GetConsensus(), pindex))
+    //{
+    //    return error("%s: UpdateHashProof(): %s", __func__, state.GetRejectReason().c_str());
+    //}
 
     // Get prev block index
     CBlockIndex* pindexPrev = nullptr;

OSX: CreateNewBlock() fails for high gas transaction

To reproduce:
1.

createcontract 6060604052341561000c57fe5b5b6101eb8061001c6000396000f30060606040526000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063561a57b214610046578063b60d428814610058575bfe5b341561004e57fe5b610056610062565b005b61006061016b565b005b600060008054806001018281610078919061016e565b916000526020600020900160005b33909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050600090505b600080549050811015610167576000818154811015156100e957fe5b906000526020600020900160005b9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc6305f5e1009081150290604051809050600060405180830381858888f19350505050151561015957fe5b5b80806001019150506100cd565b5b50565b5b565b81548183558181151161019557818360005260206000209182019101610194919061019a565b5b505050565b6101bc91905b808211156101b85760008160009055506001016101a0565b5090565b905600a165627a7a72305820ebde37344a0749ed3bea82ffe57c25c0c4fcb3ec8842d7393482ecc8938e7b6a0029 1000000 0.1
  1. mine a block:
    CreateNewBlock: TestBlockValidity failed: bad-txns-vout-negative, Transaction check failed

If the transaction is invalid, it should not make it to the mempool in the first place.

The same transaction is mined correctly on Linux.

Tx broadcast failure on sendtocontract

The test case to reproduce the issue is very similar to test 3 in the sendtocontract ITD (the issue was found while automating that ITD and running it a bunch of times). The issue only seems to appear when calling sendtocontract with a sender address.

Steps to recreate:

  1. Start qtumd in regtest mode: ./qtumd -regtest
  2. Generate 50 blocks: ./qtum-cli -regtest generate 50
  3. Create a simple contract that is payable, save its addr for later use: CONTRACT=`./qtum-cli -regtest createcontract 60606040523415600b57fe5b5b60398060196000396000f30060606040525b600b5b5b565b0000a165627a7a72305820a78094f838ccd7eb2112cf091e992aa9b37c81cdec5e47a81118bd13da3e869f0029 | python3 -c "import sys, json; print(json.load(sys.stdin)['address'])"`
  4. Mine this contract: ./qtum-cli -regtest generate 1
  5. Import the private key from test 3 of the sendtocontract ITD: ./qtum-cli -regtest importprivkey cQWxca9y9XBf4c6ohTwRQ9Kf4GZyRybhGBfzaFgkvRpw8HjbRC58
  6. Send 0.1 qtum controlled by the private key: ./qtum-cli -regtest sendtoaddress qabmqZk3re5b9UpUcznxDkCnCsnKdmPktT 0.1
  7. Mine this tx: ./qtum-cli -regtest generate 1
  8. Send 100 qtum with the address of the private key imported in step 5 as sender to the contract created in step 3: ./qtum-cli -regtest sendtocontract $CONTRACT 00 100 10000 0.00001 qabmqZk3re5b9UpUcznxDkCnCsnKdmPktT
  9. Check that the tx is in the mempool: ./qtum-cli -regtest getrawmempool
  10. If the mempool is empty the issue has been reproduced. Else mine a block and go to step 6 (try to trigger the issue again, the error occurs about 50% of the time).

Expected result:

The tx is in the mempool.

Actual result:

About 50% of the times the error below found in the log

CommitTransaction(): Transaction cannot be broadcast immediately, mandatory-script-verify-flag-failed (Script failed an OP_EQUALVERIFY operation)

Test contract source

pragma solidity ^0.4.0;
contract Test {
function () payable {}
}

Very low block maturity

I think this was changed for testing, but it will need to be changed back before testnet release. Coins are spendable from mining after just 10 blocks of maturity. This should be something much higher like 100 or 500

Possible to execute an op_call/op_create with only 1 as gas limit by setting a high gas price.

Description

Is is possible to execute an op_call or op_create with only 1 as the gas limit by setting a high gas price. The gas price should not affect the number of ops that it is possible to execute in the evm.

Steps to reproduce

  1. Start qtumd in regtest mode: ./qtumd -regtest
  2. Mine some block: ./qtum-cli -regtest generate 20
  3. Create a simple contract, set the gas limit to 1 and gas price to 1 qtum: ./qtum-cli -regtest createcontract "6060604052341561000c57fe5b5b60a38061001b6000396000f30060606040525b60755b600073abad1a14b713a967732398af0420299e9f86217a90508073ffffffffffffffffffffffffffffffffffffffff166108fc3073ffffffffffffffffffffffffffffffffffffffff16319081150290604051809050600060405180830381858888f19350505050505b50565b0000a165627a7a723058202ead4700b0995b503f46bab3274654cd832f601a2423012d5ede7fed5138392c0029" 1 1
  4. Mine this contract: ./qtum-cli -regtest generate 1
  5. List all contracts: ./qtum-cli -regtest listcontracts

Expected results:

  1. The contract should not be created since it should run out of gas due to the gas limit being 1 (setting the gas price to a high value should not affect this)

Actual results:

  1. The contract is created.

invalidateblock fails

Description

Calling invalidateblock with a block containing txs fails.

Steps to reproduce

  1. start qtumd: ./qtumd -regtest
  2. generate some blocks: ./qtum-cli -regtest generate 100
  3. check the block count: ./qtum-cli -regtest getblockcount
  4. create a new tx that sends some qtum to an address: ./qtum-cli -regtest sendtoaddress `./qtum-cli -regtest getnewaddress` 10
  5. mine this tx: ./qtum-cli -regtest generate 1
  6. invalidate the last block: ./qtum-cli -regtest invalidateblock <last block hash>

Expected behaviour

./qtum-cli -regtest getblockcount should give the same block count as in step 3.
No errors in debug.log

Actual behaviour

The block count remains what it was at step 5.
debug.log contains errors.

debug.log

2017-04-03 22:38:33 ERROR: UndoReadFromDisk: Checksum mismatch
2017-04-03 22:38:33 ERROR: DisconnectBlock(): failure reading undo data
2017-04-03 22:38:33 ERROR: DisconnectTip(): DisconnectBlock 3c433499597ab2e67c466f8da9084b1dbb2932b3a82d583171c2e1e0c549a3f7 failed

Valgrind error when using "sendtocontract"

Steps to repro:

  1. Compile with --enable-debug
  2. run using valgrind with leak-check.
  3. Mine blocks to start the chain (my chain was at block ~800)
  4. Deploy new contract (I did it from a separate node) [1]
  5. Call contract using data f7e52d58
  6. Observe valgrind log

==23814== Thread 10 bitcoin-httpworker:
==23814== Syscall param pwrite64(buf) points to uninitialised byte(s)
==23814== at 0x76B8DA3: ??? (syscall-template.S:84)
==23814== by 0x5EAECD3: __os_io (in /usr/lib/libdb_cxx-4.8.so)
==23814== by 0x5E9C50D: ??? (in /usr/lib/libdb_cxx-4.8.so)
==23814== by 0x5E9C8F1: __memp_bhwrite (in /usr/lib/libdb_cxx-4.8.so)
==23814== by 0x5EAB478: __memp_sync_int (in /usr/lib/libdb_cxx-4.8.so)
==23814== by 0x5EBCF95: __txn_checkpoint (in /usr/lib/libdb_cxx-4.8.so)
==23814== by 0x5EBD347: __txn_checkpoint_pp (in /usr/lib/libdb_cxx-4.8.so)
==23814== by 0x5D9BFBD: DbEnv::txn_checkpoint(unsigned int, unsigned int, unsigned int) (in /usr/lib/libdb_cxx-4.8.so)
==23814== by 0x7ADDC4: CDB::Flush() (db.cpp:309)
==23814== by 0x7ADEB7: CDB::Close() (db.cpp:322)
==23814== by 0x72EFFC: CDB::~CDB() (db.h:102)
==23814== by 0x72FFF6: CWalletDB::~CWalletDB() (walletdb.h:116)
==23814== Address 0x189658fe is 222 bytes inside a block of size 4,184 alloc'd
==23814== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==23814== by 0x5EAC594: __os_malloc (in /usr/lib/libdb_cxx-4.8.so)
==23814== by 0x5E7A401: __env_alloc (in /usr/lib/libdb_cxx-4.8.so)
==23814== by 0x5E9B0FE: __memp_alloc (in /usr/lib/libdb_cxx-4.8.so)
==23814== by 0x5E9E314: __memp_fget (in /usr/lib/libdb_cxx-4.8.so)
==23814== by 0x5E614B8: __db_new (in /usr/lib/libdb_cxx-4.8.so)
==23814== by 0x5DC283D: __bam_split (in /usr/lib/libdb_cxx-4.8.so)
==23814== by 0x5DAEFF2: ??? (in /usr/lib/libdb_cxx-4.8.so)
==23814== by 0x5E5198B: __dbc_iput (in /usr/lib/libdb_cxx-4.8.so)
==23814== by 0x5E45C2C: __db_put (in /usr/lib/libdb_cxx-4.8.so)
==23814== by 0x5E5EEA2: __db_put_pp (in /usr/lib/libdb_cxx-4.8.so)
==23814== by 0x5D94CDC: Db::put(DbTxn*, Dbt*, Dbt*, unsigned int) (in /usr/lib/libdb_cxx-4.8.so)
==23814==

Contract code:


pragma solidity ^0.4.0;

contract LogTest {
   uint num;
   /// Create a new ballot with $(_numProposals) different proposals.
   function LogTest() {
       CallTest();
   }
   function CallTest() public{
       num++; //not a constant function.. 
       MakeLogs();
   }
   function MakeLogs() constant public{
       //0x72ba7d8e73fe8eb666ea66babc8116a41bfb10e2
       //0x0000000000000000000000000000000000000000
        log1("0: ", 0x0000000000000000000000000000000000000000000000000000000000000000);
        log1("1: ", 0x50cb9fe53daa9737b786ab3646f04d0150dc50ef4e75f59509d83667ad5adb20);
        log1("2: ", 0x0000000000000000000000000000000000000000000000000000000000004021);
        log1("3: ", "string test");
        log1("4:", "123456");
        log2("5", "topic 1", "topic 2");
        log3("6", "topic 1", "topic 2", "topic 3");
        log4("7", "topic 1", "topic 2", "topic 3", "topic 4");
        log1("8: ", 0x4142430000000000000000000000000000000000000000000000000000004021);
        log1("9: ", 0x4142050000000000000000000000000000000000000000000000000000004021);
        log1(0x41424300, "test");
        log1(0x41420500, "test");
   }
   
   function uintToBytes(uint v) constant returns (bytes32 ret) {
       if (v == 0) {
           ret = '0';
       }
       else {
           while (v > 0) {
               ret = bytes32(uint(ret) / (2 ** 8));
               ret |= bytes32(((v % 10) + 48) * 2 ** (8 * 31));
               v /= 10;
           }
       }
       return ret;
   }
}

Refund txs vin's scriptSig is empty

Description

Refund txs vin's scriptSig does not contain OP_TXHASH and is empty.

Steps to reproduce

  1. Start qtumd: ./qtumd -regtest
  2. Mine some blocks: ./qtum-cli -regtest generate 20
  3. Create a contract and store the contract address for use later: CONTRACT=$(./qtum-cli -regtest createcontract "00" | python3 -c "import json; import sys; print(json.loads(sys.stdin.read())['address'])")
  4. Mine this contract: ./qtum-cli -regtest generate 1
  5. Send 1 qtum to the contract with too little gas which will cause a refund tx to be created: ./qtum-cli -regtest sendtocontract $CONTRACT "00" 1 1000 0.00000001
  6. Mine this tx and store the block hash for use later: BLOCKHASH=$(./qtum-cli -regtest generate 1 | python3 -c "import json; import sys; print(json.loads(sys.stdin.read())[0])")
  7. Decode the refund tx (3rd tx in the block): ./qtum-cli -regtest getrawtransaction $(./qtum-cli -regtest getblock $BLOCKHASH | python3 -c "import json; import sys; print(json.loads(sys.stdin.read())['tx'][2])") 1

Expected results:

  1. The vin's scriptSig should be OP_TXHASH

Actual results:

  1. The vin scriptSig is empty

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.