From a7c50bed41d07f4e68bb524e08d47429d73d2abe Mon Sep 17 00:00:00 2001 From: ubuntu Date: Tue, 27 Jun 2017 20:31:03 +0200 Subject: [PATCH 1/2] Added testcase for vout overflow --- qa/rpc-tests/dupe-contract.py | 55 +++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100755 qa/rpc-tests/dupe-contract.py diff --git a/qa/rpc-tests/dupe-contract.py b/qa/rpc-tests/dupe-contract.py new file mode 100755 index 0000000000..62c8e22104 --- /dev/null +++ b/qa/rpc-tests/dupe-contract.py @@ -0,0 +1,55 @@ +#!/usr/bin/env python3 +# Copyright (c) 2015-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. + +from test_framework.test_framework import BitcoinTestFramework +from test_framework.util import * +from test_framework.script import * +from test_framework.mininode import * +from test_framework.blocktools import * +from test_framework.qtum import * +import sys +import io + +class QtumDupeContractTest(BitcoinTestFramework): + def __init__(self): + super().__init__() + self.setup_clean_chain = True + self.num_nodes = 1 + + def setup_network(self, split=False): + self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, [[]]) + self.node = self.nodes[0] + + def run_test(self): + self.node.generate(10+COINBASE_MATURITY) + tx = CTransaction() + tx.vin = [make_vin(self.node, 6*COIN)] + tx.vout = [] + + # First we append two OP_CREATE outputs (vout = 0, 1 (mod 256)) + tx.vout.append(CTxOut(0, CScript([1, 1000000, 1, bytes.fromhex("60606040523415600b57fe5b5b60398060196000396000f30060606040525b600b5b5b565b0000a165627a7a72305820e3bed070fd3a81dd00e02efd22d18a3b47b70860155d6063e47e1e2674fc5acb0029"), OP_CREATE]))) + tx.vout.append(CTxOut(0, CScript([1, 1000000, 1, bytes.fromhex("60606040523415600b57fe5b5b60398060196000396000f30060606040525b600b5b5b565b0000a165627a7a72305820e3bed070fd3a81dd00e02efd22d18a3b47b70860155d6063e47e1e2674fc5acb0029"), OP_CREATE]))) + + # Now we append 255 vouts that spend no gas + for _ in range(2, 256): + tx.vout.append(CTxOut(1000000, CScript([OP_TRUE]))) + + # Now we append another two more vouts that should create contracts (vout = 0, 1 (mod 256)) + tx.vout.append(CTxOut(0, CScript([1, 1000000, 1, bytes.fromhex("60606040523415600b57fe5b5b60398060196000396000f30060606040525b600b5b5b565b0000a165627a7a72305820e3bed070fd3a81dd00e02efd22d18a3b47b70860155d6063e47e1e2674fc5acb0029"), OP_CREATE]))) + tx.vout.append(CTxOut(0, CScript([1, 1000000, 1, bytes.fromhex("60606040523415600b57fe5b5b60398060196000396000f30060606040525b600b5b5b565b0000a165627a7a72305820e3bed070fd3a81dd00e02efd22d18a3b47b70860155d6063e47e1e2674fc5acb0029"), OP_CREATE]))) + + ret = self.node.signrawtransaction(bytes_to_hex_str(tx.serialize())) + self.node.sendrawtransaction(ret['hex']) + self.node.generate(1) + + # This should result in 4 contracts being created. + assert_equal(len(self.node.listcontracts()), 4) + + + + + +if __name__ == '__main__': + QtumDupeContractTest().main() From b5402482bf311c5d3842f069d44028a417d437b5 Mon Sep 17 00:00:00 2001 From: Neil Date: Tue, 27 Jun 2017 23:37:49 +0000 Subject: [PATCH 2/2] fix vout overflow --- src/qtum/qtumstate.cpp | 5 ++++- src/wallet/rpcwallet.cpp | 10 +++++++--- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/qtum/qtumstate.cpp b/src/qtum/qtumstate.cpp index c05dc16869..7ca491b4d7 100644 --- a/src/qtum/qtumstate.cpp +++ b/src/qtum/qtumstate.cpp @@ -213,7 +213,10 @@ void QtumState::addBalance(dev::Address const& _id, dev::u256 const& _amount) dev::Address QtumState::createQtumAddress(dev::h256 hashTx, uint32_t voutNumber){ uint256 hashTXid(h256Touint(hashTx)); std::vector txIdAndVout(hashTXid.begin(), hashTXid.end()); - txIdAndVout.push_back(voutNumber); + std::vector voutNumberChrs; + if (voutNumberChrs.size() < sizeof(voutNumber))voutNumberChrs.resize(sizeof(voutNumber)); + std::memcpy(voutNumberChrs.data(), &voutNumber, sizeof(voutNumber)); + txIdAndVout.insert(txIdAndVout.end(),voutNumberChrs.begin(),voutNumberChrs.end()); std::vector SHA256TxVout(32); CSHA256().Write(txIdAndVout.data(), txIdAndVout.size()).Finalize(SHA256TxVout.data()); diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index a51cb04dba..ca7bc58f29 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -596,12 +596,16 @@ UniValue createcontract(const JSONRPCRequest& request){ std::vector SHA256TxVout(32); vector contractAddress(20); vector txIdAndVout(wtx.GetHash().begin(), wtx.GetHash().end()); - unsigned char nOut=0; + uint32_t voutNumber=0; BOOST_FOREACH(const CTxOut& txout, wtx.tx->vout) { if(txout.scriptPubKey.HasOpCreate()){ - txIdAndVout.push_back(nOut); + std::vector voutNumberChrs; + if (voutNumberChrs.size() < sizeof(voutNumber))voutNumberChrs.resize(sizeof(voutNumber)); + std::memcpy(voutNumberChrs.data(), &voutNumber, sizeof(voutNumber)); + txIdAndVout.insert(txIdAndVout.end(),voutNumberChrs.begin(),voutNumberChrs.end()); + break; } - nOut++; + voutNumber++; } CSHA256().Write(txIdAndVout.data(), txIdAndVout.size()).Finalize(SHA256TxVout.data()); CRIPEMD160().Write(SHA256TxVout.data(), SHA256TxVout.size()).Finalize(contractAddress.data());